From ba36814d8dd0c7e34f9eb12480817ae1f61f2c69 Mon Sep 17 00:00:00 2001 From: Azareal Date: Sun, 3 Sep 2017 05:50:31 +0100 Subject: [PATCH] Refactored the code to follow best standards better. Added Basic IP Search. Added more items to .gitignore Add a VSCode settings file. Refactored the theme system to allow me to add a per-user theme switcher in the following commit. Fixed h1s, rowmenus, profiles and the Control Panel Dashboard on Tempra Simple. We now catch more extreme edge case errors. Renamed route_panel_themes_default to route_panel_themes_set_default. Centralised some of the per-route ExtData fields. Added an ExtData field to headerLite. Moved SettingLabels into the Phrase System. --- .gitignore | 4 + .vscode/settings.json | 4 + alerts.go | 145 +-- auth.go | 83 +- cache.go | 11 +- database.go | 43 +- errors.go | 284 ++--- experimental/plugin_geoip.go | 19 + extend.go | 309 +++--- files.go | 64 +- forum.go | 51 +- forum_store.go | 135 ++- gen_mysql.go | 2 + gen_pgsql.go | 2 + gen_router.go | 2 +- general_test.go | 375 ++----- group.go | 93 +- install/install.go | 242 +++-- install/mysql.go | 63 +- install/pgsql.go | 37 +- install/utils.go | 15 +- main.go | 121 ++- misc_test.go | 339 +++--- mod_routes.go | 489 +++++---- mysql.go | 33 +- no_websockets.go | 17 +- pages.go | 885 ++++++++-------- panel_routes.go | 1347 ++++++++++++------------ permissions.go | 409 +++---- phrases.go | 146 +-- plugin_bbcode.go | 408 +++---- plugin_helloworld.go | 12 +- plugin_markdown.go | 448 ++++---- plugin_skeleton.go | 8 +- plugin_socialgroups.go | 578 +++++----- plugin_test.go | 393 ++++--- public/global.js | 6 +- query_gen/lib/install.go | 20 +- query_gen/lib/mysql.go | 577 +++++----- query_gen/lib/pgsql.go | 123 +-- query_gen/lib/utils.go | 195 ++-- reply.go | 90 +- router_gen/routes.go | 94 +- routes.go | 1103 +++++++++---------- setting.go | 27 +- tasks.go | 4 +- template_forum.go | 69 +- template_forums.go | 65 +- template_init.go | 140 +-- template_list.go | 697 ++++++------ template_profile.go | 73 +- template_topic.go | 175 +-- template_topic_alt.go | 73 +- template_topics.go | 71 +- templates.go | 1161 ++++++++++---------- templates/forum.html | 6 +- templates/header.html | 4 +- templates/ip-search.html | 18 + templates/menu.html | 2 +- templates/panel-inner-menu.html | 2 +- templates/panel-users.html | 4 +- templates/profile.html | 8 +- templates/socialgroups_view_group.html | 4 +- templates/topic.html | 6 +- templates/topic_alt.html | 8 +- templates/topics.html | 6 +- themes.go | 460 ++++---- themes/shadow/public/main.css | 3 + themes/tempra-simple/public/main.css | 41 +- themes/tempra-simple/public/panel.css | 4 + topic.go | 158 +-- topic_store.go | 74 +- user.go | 291 ++--- user_store.go | 244 ++--- utils.go | 205 ++-- websockets.go | 257 +++-- widgets.go | 72 +- 77 files changed, 7264 insertions(+), 6992 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 experimental/plugin_geoip.go create mode 100644 templates/ip-search.html diff --git a/.gitignore b/.gitignore index f92a5141..f2b3649c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ tmp/* tmp2/* cert_test/* +tmp.txt +run_notemplategen.bat +brun.bat uploads/avatar_* uploads/socialgroup_* @@ -10,3 +13,4 @@ bin/* *.prof *.log .DS_Store +.vscode/launch.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..0231b2a8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "editor.insertSpaces": false +} \ No newline at end of file diff --git a/alerts.go b/alerts.go index 0aa57655..d6fe8ba3 100644 --- a/alerts.go +++ b/alerts.go @@ -1,3 +1,9 @@ +/* +* +* Gosora Alerts System +* Copyright Azareal 2017 - 2018 +* + */ package main import "log" @@ -20,10 +26,10 @@ import "errors" "{x}{created a new topic}{topic}" */ -func build_alert(asid int, event string, elementType string, actor_id int, targetUser_id int, elementID int, user User /* The current user */) (string, error) { +func buildAlert(asid int, event string, elementType string, actorID int, targetUserID int, elementID int, user User /* The current user */) (string, error) { var targetUser *User - actor, err := users.CascadeGet(actor_id) + actor, err := users.CascadeGet(actorID) if err != nil { return "", errors.New("Unable to find the actor") } @@ -37,84 +43,85 @@ func build_alert(asid int, event string, elementType string, actor_id int, targe }*/ if event == "friend_invite" { - return `{"msg":"You received a friend invite from {0}","sub":["` + actor.Name + `"],"path":"`+actor.Link+`","avatar":"`+strings.Replace(actor.Avatar,"/","\\/",-1)+`","asid":"`+strconv.Itoa(asid)+`"}`, nil + return `{"msg":"You received a friend invite from {0}","sub":["` + actor.Name + `"],"path":"` + actor.Link + `","avatar":"` + strings.Replace(actor.Avatar, "/", "\\/", -1) + `","asid":"` + strconv.Itoa(asid) + `"}`, nil } - var act, post_act, url, area string - var start_frag, end_frag string - switch(elementType) { - case "forum": - if event == "reply" { - act = "created a new topic" - topic, err := topics.CascadeGet(elementID) - if err != nil { - return "", errors.New("Unable to find the linked topic") - } - url = topic.Link - area = topic.Title - // Store the forum ID in the targetUser column instead of making a new one? o.O - // Add an additional column for extra information later on when we add the ability to link directly to posts. We don't need the forum data for now... - } else { - act = "did something in a forum" - } - case "topic": + var act, postAct, url, area string + var startFrag, endFrag string + switch elementType { + case "forum": + if event == "reply" { + act = "created a new topic" topic, err := topics.CascadeGet(elementID) if err != nil { return "", errors.New("Unable to find the linked topic") } url = topic.Link area = topic.Title + // Store the forum ID in the targetUser column instead of making a new one? o.O + // Add an additional column for extra information later on when we add the ability to link directly to posts. We don't need the forum data for now... + } else { + act = "did something in a forum" + } + case "topic": + topic, err := topics.CascadeGet(elementID) + if err != nil { + return "", errors.New("Unable to find the linked topic") + } + url = topic.Link + area = topic.Title - if targetUser_id == user.ID { - post_act = " your topic" - } - case "user": - targetUser, err = users.CascadeGet(elementID) - if err != nil { - return "", errors.New("Unable to find the target user") - } - area = targetUser.Name - end_frag = "'s profile" - url = targetUser.Link - case "post": - topic, err := get_topic_by_reply(elementID) - if err != nil { - return "", errors.New("Unable to find the linked reply or parent topic") - } - url = topic.Link - area = topic.Title - if targetUser_id == user.ID { - post_act = " your post in" - } - default: - return "", errors.New("Invalid elementType") + if targetUserID == user.ID { + postAct = " your topic" + } + case "user": + targetUser, err = users.CascadeGet(elementID) + if err != nil { + return "", errors.New("Unable to find the target user") + } + area = targetUser.Name + endFrag = "'s profile" + url = targetUser.Link + case "post": + topic, err := getTopicByReply(elementID) + if err != nil { + return "", errors.New("Unable to find the linked reply or parent topic") + } + url = topic.Link + area = topic.Title + if targetUserID == user.ID { + postAct = " your post in" + } + default: + return "", errors.New("Invalid elementType") } - switch(event) { - case "like": - if elementType == "user" { - act = "likes" - end_frag = "" - if targetUser.ID == user.ID { - area = "you" - } - } else { - act = "liked" + switch event { + case "like": + if elementType == "user" { + act = "likes" + endFrag = "" + if targetUser.ID == user.ID { + area = "you" } - case "mention": - if elementType == "user" { - act = "mentioned you on" - } else { - act = "mentioned you in" - post_act = "" - } - case "reply": act = "replied to" + } else { + act = "liked" + } + case "mention": + if elementType == "user" { + act = "mentioned you on" + } else { + act = "mentioned you in" + postAct = "" + } + case "reply": + act = "replied to" } - return `{"msg":"{0} ` + start_frag + act + post_act + ` {1}` + end_frag + `","sub":["` + actor.Name + `","` + area + `"],"path":"` + url + `","avatar":"` + actor.Avatar + `","asid":"`+strconv.Itoa(asid)+`"}`, nil + return `{"msg":"{0} ` + startFrag + act + postAct + ` {1}` + endFrag + `","sub":["` + actor.Name + `","` + area + `"],"path":"` + url + `","avatar":"` + actor.Avatar + `","asid":"` + strconv.Itoa(asid) + `"}`, nil } -func notify_watchers(asid int64) { +func notifyWatchers(asid int64) { rows, err := get_watchers_stmt.Query(asid) if err != nil && err != ErrNoRows { log.Fatal(err.Error()) @@ -129,22 +136,22 @@ func notify_watchers(asid int64) { log.Fatal(err.Error()) return } - uids = append(uids,uid) + uids = append(uids, uid) } err = rows.Err() if err != nil { log.Fatal(err.Error()) return } - rows.Close() + _ = rows.Close() - var actor_id, targetUser_id, elementID int + var actorID, targetUserID, elementID int var event, elementType string - err = get_activity_entry_stmt.QueryRow(asid).Scan(&actor_id, &targetUser_id, &event, &elementType, &elementID) + err = get_activity_entry_stmt.QueryRow(asid).Scan(&actorID, &targetUserID, &event, &elementType, &elementID) if err != nil && err != ErrNoRows { log.Fatal(err.Error()) return } - _ = ws_hub.push_alerts(uids, int(asid), event, elementType, actor_id, targetUser_id, elementID) + _ = wsHub.pushAlerts(uids, int(asid), event, elementType, actorID, targetUserID, elementID) } diff --git a/auth.go b/auth.go index 755e6106..e67310c7 100644 --- a/auth.go +++ b/auth.go @@ -1,4 +1,9 @@ -/* Work in progress */ +/* +* +* Gosora Authentication Interface +* Copyright Azareal 2017 - 2018 +* + */ package main import "log" @@ -11,11 +16,15 @@ import "./query_gen/lib" import "golang.org/x/crypto/bcrypt" var auth Auth -var ErrMismatchedHashAndPassword = bcrypt.ErrMismatchedHashAndPassword -var ErrPasswordTooLong = errors.New("The password you selected is too long") // Silly, but we don't want bcrypt to bork on us -type Auth interface -{ +// ErrMismatchedHashAndPassword is thrown whenever a hash doesn't match it's unhashed password +var ErrMismatchedHashAndPassword = bcrypt.ErrMismatchedHashAndPassword + +// ErrPasswordTooLong is silly, but we don't want bcrypt to bork on us +var ErrPasswordTooLong = errors.New("The password you selected is too long") + +// Auth is the main authentication interface. +type Auth interface { Authenticate(username string, password string) (uid int, err error) Logout(w http.ResponseWriter, uid int) ForceLogout(uid int) error @@ -25,82 +34,86 @@ type Auth interface CreateSession(uid int) (session string, err error) } -type DefaultAuth struct -{ - login *sql.Stmt +// DefaultAuth is the default authenticator used by Gosora, may be swapped with an alternate authenticator in some situations. E.g. To support LDAP. +type DefaultAuth struct { + login *sql.Stmt logout *sql.Stmt } +// NewDefaultAuth is a factory for spitting out DefaultAuths func NewDefaultAuth() *DefaultAuth { - login_stmt, err := qgen.Builder.SimpleSelect("users","uid, password, salt","name = ?","","") + loginStmt, err := qgen.Builder.SimpleSelect("users", "uid, password, salt", "name = ?", "", "") if err != nil { log.Fatal(err) } - logout_stmt, err := qgen.Builder.SimpleUpdate("users","session = ''","uid = ?") + logoutStmt, err := qgen.Builder.SimpleUpdate("users", "session = ''", "uid = ?") if err != nil { log.Fatal(err) } return &DefaultAuth{ - login: login_stmt, - logout: logout_stmt, + login: loginStmt, + logout: logoutStmt, } } +// Authenticate checks if a specific username and password is valid and returns the UID for the corresponding user, if so. Otherwise, a user safe error. func (auth *DefaultAuth) Authenticate(username string, password string) (uid int, err error) { - var real_password, salt string - err = auth.login.QueryRow(username).Scan(&uid, &real_password, &salt) + var realPassword, salt string + err = auth.login.QueryRow(username).Scan(&uid, &realPassword, &salt) if err == ErrNoRows { - return 0, errors.New("We couldn't find an account with that username.") + return 0, errors.New("We couldn't find an account with that username.") // nolint } else if err != nil { LogError(err) - return 0, errors.New("There was a glitch in the system. Please contact the system administrator.") + return 0, errors.New("There was a glitch in the system. Please contact your local administrator.") // nolint } if salt == "" { // Send an email to admin for this? LogError(errors.New("Missing salt for user #" + strconv.Itoa(uid) + ". Potential security breach.")) - return 0, errors.New("There was a glitch in the system. Please contact the system administrator.") + return 0, errors.New("There was a glitch in the system. Please contact your local administrator") } - err = CheckPassword(real_password,password,salt) + err = CheckPassword(realPassword, password, salt) if err == ErrMismatchedHashAndPassword { return 0, errors.New("That's not the correct password.") } else if err != nil { LogError(err) - return 0, errors.New("There was a glitch in the system. Please contact the system administrator.") + return 0, errors.New("There was a glitch in the system. Please contact your local administrator.") } return uid, nil } +// ForceLogout logs the user out of every computer, not just the one they logged out of func (auth *DefaultAuth) ForceLogout(uid int) error { _, err := auth.logout.Exec(uid) if err != nil { LogError(err) - return errors.New("There was a glitch in the system. Please contact the system administrator.") + return errors.New("There was a glitch in the system. Please contact your local administrator.") } // Flush the user out of the cache and reload err = users.Load(uid) if err != nil { - return errors.New("Your account no longer exists!") + return errors.New("Your account no longer exists.") } return nil } +// Logout logs you out of the computer you requested the logout for, but not the other computers you're logged in with func (auth *DefaultAuth) Logout(w http.ResponseWriter, _ int) { - cookie := http.Cookie{Name:"uid",Value:"",Path:"/",MaxAge: year} - http.SetCookie(w,&cookie) - cookie = http.Cookie{Name:"session",Value:"",Path:"/",MaxAge: year} - http.SetCookie(w,&cookie) + cookie := http.Cookie{Name: "uid", Value: "", Path: "/", MaxAge: year} + http.SetCookie(w, &cookie) + cookie = http.Cookie{Name: "session", Value: "", Path: "/", MaxAge: year} + http.SetCookie(w, &cookie) } func (auth *DefaultAuth) SetCookies(w http.ResponseWriter, uid int, session string) { - cookie := http.Cookie{Name: "uid",Value: strconv.Itoa(uid),Path: "/",MaxAge: year} - http.SetCookie(w,&cookie) - cookie = http.Cookie{Name: "session",Value: session,Path: "/",MaxAge: year} - http.SetCookie(w,&cookie) + cookie := http.Cookie{Name: "uid", Value: strconv.Itoa(uid), Path: "/", MaxAge: year} + http.SetCookie(w, &cookie) + cookie = http.Cookie{Name: "session", Value: session, Path: "/", MaxAge: year} + http.SetCookie(w, &cookie) } func (auth *DefaultAuth) GetCookies(r *http.Request) (uid int, session string, err error) { @@ -123,26 +136,26 @@ func (auth *DefaultAuth) GetCookies(r *http.Request) (uid int, session string, e func (auth *DefaultAuth) SessionCheck(w http.ResponseWriter, r *http.Request) (user *User, halt bool) { uid, session, err := auth.GetCookies(r) if err != nil { - return &guest_user, false + return &guestUser, false } // Is this session valid..? user, err = users.CascadeGet(uid) if err == ErrNoRows { - return &guest_user, false + return &guestUser, false } else if err != nil { - InternalError(err,w) - return &guest_user, true + InternalError(err, w) + return &guestUser, true } if user.Session == "" || session != user.Session { - return &guest_user, false + return &guestUser, false } return user, false } -func(auth *DefaultAuth) CreateSession(uid int) (session string, err error) { +func (auth *DefaultAuth) CreateSession(uid int) (session string, err error) { session, err = GenerateSafeString(sessionLength) if err != nil { return "", err diff --git a/cache.go b/cache.go index 56a38ed7..8aa82197 100644 --- a/cache.go +++ b/cache.go @@ -1,13 +1,20 @@ package main + import "errors" +// Go away, linter. We need to differentiate constants from variables somehow ;) +// nolint const CACHE_STATIC int = 0 const CACHE_DYNAMIC int = 1 const CACHE_SQL int = 2 -var ErrCacheDesync = errors.New("The cache is out of synchronisation with the database.") // TO-DO: A cross-server synchronisation mechanism -var ErrStoreCapacityOverflow = errors.New("This datastore has already reached it's max capacity") +// ErrCacheDesync is thrown whenever a piece of data, for instance, a user is out of sync with the database. Currently unused. +var ErrCacheDesync = errors.New("The cache is out of sync with the database.") // TO-DO: A cross-server synchronisation mechanism +// ErrStoreCapacityOverflow is thrown whenever a datastore reaches it's maximum hard capacity. I'm not sure *if* this one is used, at the moment. Probably. +var ErrStoreCapacityOverflow = errors.New("This datastore has reached it's maximum capacity.") + +// nolint type DataStore interface { Load(id int) error Get(id int) (interface{}, error) diff --git a/database.go b/database.go index ea501d9a..d1f39d08 100644 --- a/database.go +++ b/database.go @@ -5,20 +5,21 @@ import "encoding/json" import "database/sql" var db *sql.DB -var db_version string -var db_adapter string +var dbVersion string +var dbAdapter string +// ErrNoRows is an alias of sql.ErrNoRows, just in case we end up with non-database/sql datastores var ErrNoRows = sql.ErrNoRows -func init_database() (err error) { - // Engine specific code - err = _init_database() - if err != nil { - return err - } +func initDatabase() (err error) { + // Engine specific code + err = _initDatabase() + if err != nil { + return err + } - log.Print("Loading the usergroups.") - groups = append(groups, Group{ID:0,Name:"System"}) + log.Print("Loading the usergroups.") + groups = append(groups, Group{ID: 0, Name: "System"}) rows, err := get_groups_stmt.Query() if err != nil { @@ -27,9 +28,9 @@ func init_database() (err error) { defer rows.Close() i := 1 - for ;rows.Next();i++ { - group := Group{ID: 0,} - err := rows.Scan(&group.ID, &group.Name, &group.PermissionsText, &group.PluginPermsText, &group.Is_Mod, &group.Is_Admin, &group.Is_Banned, &group.Tag) + for ; rows.Next(); i++ { + group := Group{ID: 0} + err := rows.Scan(&group.ID, &group.Name, &group.PermissionsText, &group.PluginPermsText, &group.IsMod, &group.IsAdmin, &group.IsBanned, &group.Tag) if err != nil { return err } @@ -37,7 +38,7 @@ func init_database() (err error) { // Ugh, you really shouldn't physically delete these items, it makes a big mess of things if group.ID != i { log.Print("Stop physically deleting groups. You are messing up the IDs. Use the Group Manager or delete_group() instead x.x") - fill_group_id_gap(i, group.ID) + fillGroupIDGap(i, group.ID) } err = json.Unmarshal(group.PermissionsText, &group.Perms) @@ -49,7 +50,7 @@ func init_database() (err error) { log.Printf("%+v\n", group.Perms) } - err = json.Unmarshal(group.PluginPermsText, &group.PluginPerms) + err = json.Unmarshal(group.PluginPermsText, &group.PluginPerms) if err != nil { return err } @@ -71,19 +72,18 @@ func init_database() (err error) { GuestPerms = groups[6].Perms log.Print("Loading the forums.") - fstore = NewStaticForumStore() + fstore = NewStaticForumStore() err = fstore.LoadForums() if err != nil { return err } log.Print("Loading the forum permissions.") - err = build_forum_permissions() + err = buildForumPermissions() if err != nil { return err } - log.Print("Loading the settings.") err = LoadSettings() if err != nil { @@ -97,10 +97,5 @@ func init_database() (err error) { } log.Print("Loading the themes.") - err = LoadThemes() - if err != nil { - return err - } - - return nil + return LoadThemes() } diff --git a/errors.go b/errors.go index a6c07b5a..98e4e308 100644 --- a/errors.go +++ b/errors.go @@ -8,283 +8,331 @@ import "net/http" import "runtime/debug" // TO-DO: Use the error_buffer variable to construct the system log in the Control Panel. Should we log errors caused by users too? Or just collect statistics on those or do nothing? Intercept recover()? Could we intercept the logger instead here? We might get too much information, if we intercept the logger, maybe make it part of the Debug page? -var error_buffer_mutex sync.RWMutex -var error_buffer []error +var errorBufferMutex sync.RWMutex +var errorBuffer []error + //var notfound_count_per_second int //var noperms_count_per_second int -var error_internal []byte -var error_notfound []byte +var errorInternal []byte +var errorNotfound []byte -func init_errors() error { +func initErrors() error { var b bytes.Buffer - user := User{0,"guest","Guest","",0,false,false,false,false,false,false,GuestPerms,nil,"",false,"","","","","",0,0,"0.0.0.0.0",0} - pi := Page{"Internal Server Error",user,hvars,tList,"A problem has occurred in the system."} - err := templates.ExecuteTemplate(&b,"error.html", pi) + user := User{0, "guest", "Guest", "", 0, false, false, false, false, false, false, GuestPerms, nil, "", false, "", "", "", "", "", 0, 0, "0.0.0.0.0", 0} + pi := Page{"Internal Server Error", user, hvars, tList, "A problem has occurred in the system."} + err := templates.ExecuteTemplate(&b, "error.html", pi) if err != nil { return err } - error_internal = b.Bytes() + errorInternal = b.Bytes() b.Reset() - pi = Page{"Not Found",user,hvars,tList,"The requested page doesn't exist."} - err = templates.ExecuteTemplate(&b,"error.html", pi) + pi = Page{"Not Found", user, hvars, tList, "The requested page doesn't exist."} + err = templates.ExecuteTemplate(&b, "error.html", pi) if err != nil { return err } - error_notfound = b.Bytes() + errorNotfound = b.Bytes() return nil } +// LogError logs internal handler errors which can't be handled with InternalError() as a wrapper for log.Fatal(), we might do more with it in the future func LogError(err error) { log.Print(err) debug.PrintStack() - error_buffer_mutex.Lock() - defer error_buffer_mutex.Unlock() - error_buffer = append(error_buffer,err) + errorBufferMutex.Lock() + defer errorBufferMutex.Unlock() + errorBuffer = append(errorBuffer, err) log.Fatal("") } +// InternalError is the main function for handling internal errors, while simultaneously printing out a page for the end-user to let them know that *something* has gone wrong func InternalError(err error, w http.ResponseWriter) { - w.Write(error_internal) + _, _ = w.Write(errorInternal) log.Print(err) debug.PrintStack() - error_buffer_mutex.Lock() - defer error_buffer_mutex.Unlock() - error_buffer = append(error_buffer,err) + errorBufferMutex.Lock() + defer errorBufferMutex.Unlock() + errorBuffer = append(errorBuffer, err) log.Fatal("") } -func InternalErrorJSQ(err error, w http.ResponseWriter, r *http.Request, is_js string) { +// InternalErrorJSQ is the JSON "maybe" version of InternalError which can handle both JSON and normal requests +func InternalErrorJSQ(err error, w http.ResponseWriter, r *http.Request, isJs bool) { w.WriteHeader(500) - if is_js == "0" { - w.Write(error_internal) + if !isJs { + _, _ = w.Write(errorInternal) } else { - w.Write([]byte(`{"errmsg":"A problem has occured in the system."}`)) + _, _ = w.Write([]byte(`{"errmsg":"A problem has occured in the system."}`)) } log.Print(err) debug.PrintStack() - error_buffer_mutex.Lock() - defer error_buffer_mutex.Unlock() - error_buffer = append(error_buffer,err) + errorBufferMutex.Lock() + defer errorBufferMutex.Unlock() + errorBuffer = append(errorBuffer, err) log.Fatal("") } +// InternalErrorJS is the JSON version of InternalError on routes we know will only be requested via JSON. E.g. An API. func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) { w.WriteHeader(500) - w.Write([]byte(`{"errmsg":"A problem has occured in the system."}`)) - error_buffer_mutex.Lock() - defer error_buffer_mutex.Unlock() - error_buffer = append(error_buffer,err) + _, _ = w.Write([]byte(`{"errmsg":"A problem has occured in the system."}`)) + errorBufferMutex.Lock() + defer errorBufferMutex.Unlock() + errorBuffer = append(errorBuffer, err) log.Fatal(err) } func PreError(errmsg string, w http.ResponseWriter, r *http.Request) { w.WriteHeader(500) - user := User{ID:0,Group:6,Perms:GuestPerms,} - pi := Page{"Error",user,hvars,tList,errmsg} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + user := User{ID: 0, Group: 6, Perms: GuestPerms} + pi := Page{"Error", user, hvars, tList, errmsg} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html",pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User) { w.WriteHeader(500) - pi := Page{"Local Error",user,hvars,tList,errmsg} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + pi := Page{"Local Error", user, hvars, tList, errmsg} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html",pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } func LoginRequired(w http.ResponseWriter, r *http.Request, user User) { w.WriteHeader(401) - pi := Page{"Local Error",user,hvars,tList,"You need to login to do that."} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + pi := Page{"Local Error", user, hvars, tList, "You need to login to do that."} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html",pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } func PreErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) { w.WriteHeader(500) - w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) + _, _ = w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) } -func PreErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, is_js string) { +func PreErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, isJs bool) { w.WriteHeader(500) - if is_js == "0" { - user := User{ID:0,Group:6,Perms:GuestPerms,} - pi := Page{"Local Error",user,hvars,tList,errmsg} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + if !isJs { + user := User{ID: 0, Group: 6, Perms: GuestPerms} + pi := Page{"Local Error", user, hvars, tList, errmsg} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } else { - w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) + _, _ = w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) } } -func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user User, is_js string) { +func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user User, isJs bool) { w.WriteHeader(500) - if is_js == "0" { - pi := Page{"Local Error",user,hvars,tList,errmsg} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + if !isJs { + pi := Page{"Local Error", user, hvars, tList, errmsg} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } else { - w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) + _, _ = w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) } } func LocalErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) { w.WriteHeader(500) - w.Write([]byte(`{'errmsg': '` + errmsg + `'}`)) + _, _ = w.Write([]byte(`{'errmsg': '` + errmsg + `'}`)) } func NoPermissions(w http.ResponseWriter, r *http.Request, user User) { w.WriteHeader(403) - pi := Page{"Local Error",user,hvars,tList,"You don't have permission to do that."} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + pi := Page{"Local Error", user, hvars, tList, "You don't have permission to do that."} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } errpage := b.String() - fmt.Fprintln(w,errpage) + fmt.Fprintln(w, errpage) } -func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { +func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bool) { w.WriteHeader(403) - if is_js == "0" { - pi := Page{"Local Error",user,hvars,tList,"You don't have permission to do that."} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + if !isJs { + pi := Page{"Local Error", user, hvars, tList, "You don't have permission to do that."} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } else { - w.Write([]byte(`{"errmsg":"You don't have permission to do that."}`)) + _, _ = w.Write([]byte(`{"errmsg":"You don't have permission to do that."}`)) } } func Banned(w http.ResponseWriter, r *http.Request, user User) { w.WriteHeader(403) - pi := Page{"Banned",user,hvars,tList,"You have been banned from this site."} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + pi := Page{"Banned", user, hvars, tList, "You have been banned from this site."} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } -func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { +// nolint +func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bool) { w.WriteHeader(403) - if is_js == "0" { - pi := Page{"Banned",user,hvars,tList,"You have been banned from this site."} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + if !isJs { + pi := Page{"Banned", user, hvars, tList, "You have been banned from this site."} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } else { - w.Write([]byte(`{"errmsg":"You have been banned from this site."}`)) + _, _ = w.Write([]byte(`{"errmsg":"You have been banned from this site."}`)) } } -func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { +// nolint +func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bool) { w.WriteHeader(401) - if is_js == "0" { - pi := Page{"Local Error",user,hvars,tList,"You need to login to do that."} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + if !isJs { + pi := Page{"Local Error", user, hvars, tList, "You need to login to do that."} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } else { - w.Write([]byte(`{"errmsg":"You need to login to do that."}`)) + _, _ = w.Write([]byte(`{"errmsg":"You need to login to do that."}`)) } } func SecurityError(w http.ResponseWriter, r *http.Request, user User) { w.WriteHeader(403) - pi := Page{"Security Error",user,hvars,tList,"There was a security issue with your request."} - if pre_render_hooks["pre_render_security_error"] != nil { - if run_pre_render_hook("pre_render_security_error", w, r, &user, &pi) { + pi := Page{"Security Error", user, hvars, tList, "There was a security issue with your request."} + if preRenderHooks["pre_render_security_error"] != nil { + if runPreRenderHook("pre_render_security_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } func NotFound(w http.ResponseWriter, r *http.Request) { w.WriteHeader(404) - w.Write(error_notfound) + _, _ = w.Write(errorNotfound) } +// nolint func CustomError(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, user User) { w.WriteHeader(errcode) - pi := Page{errtitle,user,hvars,tList,errmsg} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + pi := Page{errtitle, user, hvars, tList, errmsg} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } -func CustomErrorJSQ(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, user User, is_js string) { +// nolint +func CustomErrorJSQ(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, user User, isJs bool) { w.WriteHeader(errcode) - if is_js == "0" { - pi := Page{errtitle,user,hvars,tList,errmsg} - if pre_render_hooks["pre_render_error"] != nil { - if run_pre_render_hook("pre_render_error", w, r, &user, &pi) { + if !isJs { + pi := Page{errtitle, user, hvars, tList, errmsg} + if preRenderHooks["pre_render_error"] != nil { + if runPreRenderHook("pre_render_error", w, r, &user, &pi) { return } } var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - fmt.Fprintln(w,b.String()) + err := templates.ExecuteTemplate(&b, "error.html", pi) + if err != nil { + LogError(err) + } + fmt.Fprintln(w, b.String()) } else { - w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) + _, _ = w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) } } diff --git a/experimental/plugin_geoip.go b/experimental/plugin_geoip.go new file mode 100644 index 00000000..6531df7f --- /dev/null +++ b/experimental/plugin_geoip.go @@ -0,0 +1,19 @@ +package main + +import "github.com/oschwald/geoip2-golang" + +var geoip_db *geoip.DB +var geoip_db_location string = "geoip_db.mmdb" + +func init() { + plugins["geoip"] = NewPlugin("geoip","Geoip","Azareal","http://github.com/Azareal","","","",init_geoip,nil,deactivate_geoip,nil,nil) +} + +func init_geoip() (err error) { + geoip_db, err = geoip2.Open(geoip_db_location) + return err +} + +func deactivate_geoip() { + geoip_db.Close() +} diff --git a/extend.go b/extend.go index 75f62d75..36c316ba 100644 --- a/extend.go +++ b/extend.go @@ -1,95 +1,101 @@ -/* Copyright Azareal 2016 - 2018 */ +/* +* +* Gosora Plugin System +* Copyright Azareal 2016 - 2018 +* + */ package main + import "log" import "net/http" -var plugins map[string]*Plugin = make(map[string]*Plugin) +var plugins = make(map[string]*Plugin) // Hooks with a single argument. Is this redundant? Might be useful for inlining, as variadics aren't inlined? Are closures even inlined to begin with? -var hooks map[string][]func(interface{})interface{} = map[string][]func(interface{})interface{}{ - "forums_frow_assign": nil, +var hooks = map[string][]func(interface{}) interface{}{ + "forums_frow_assign": nil, "topic_create_frow_assign": nil, - "rrow_assign": nil, // TO-DO: Rename this hook to topic_rrow_assign + "rrow_assign": nil, // TO-DO: Rename this hook to topic_rrow_assign } // Hooks with a variable number of arguments -var vhooks map[string]func(...interface{})interface{} = map[string]func(...interface{})interface{}{ +var vhooks = map[string]func(...interface{}) interface{}{ "simple_forum_check_pre_perms": nil, - "forum_check_pre_perms": nil, - "intercept_build_widgets": nil, - "forum_trow_assign": nil, - "topics_topic_row_assign": nil, + "forum_check_pre_perms": nil, + "intercept_build_widgets": nil, + "forum_trow_assign": nil, + "topics_topic_row_assign": nil, //"topics_user_row_assign": nil, "create_group_preappend": nil, // What is this? Investigate! - "topic_create_pre_loop": nil, + "topic_create_pre_loop": nil, } // Hooks which take in and spit out a string. This is usually used for parser components -var sshooks map[string][]func(string)string = map[string][]func(string)string{ +var sshooks = map[string][]func(string) string{ "preparse_preassign": nil, - "parse_assign": nil, + "parse_assign": nil, } // The hooks which run before the template is rendered for a route -var pre_render_hooks map[string][]func(http.ResponseWriter, *http.Request, *User, interface{})bool = map[string][]func(http.ResponseWriter, *http.Request, *User, interface{})bool{ +var preRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User, interface{}) bool{ "pre_render": nil, - "pre_render_forum_list": nil, - "pre_render_view_forum": nil, - "pre_render_topic_list": nil, - "pre_render_view_topic": nil, - "pre_render_profile": nil, - "pre_render_custom_page": nil, - "pre_render_overview": nil, + "pre_render_forum_list": nil, + "pre_render_view_forum": nil, + "pre_render_topic_list": nil, + "pre_render_view_topic": nil, + "pre_render_profile": nil, + "pre_render_custom_page": nil, + "pre_render_overview": nil, "pre_render_create_topic": nil, "pre_render_account_own_edit_critical": nil, - "pre_render_account_own_edit_avatar": nil, + "pre_render_account_own_edit_avatar": nil, "pre_render_account_own_edit_username": nil, - "pre_render_account_own_edit_email": nil, - "pre_render_login": nil, - "pre_render_register": nil, - "pre_render_ban": nil, + "pre_render_account_own_edit_email": nil, + "pre_render_login": nil, + "pre_render_register": nil, + "pre_render_ban": nil, + "pre_render_ips": nil, - "pre_render_panel_dashboard": nil, - "pre_render_panel_forums": nil, - "pre_render_panel_delete_forum": nil, - "pre_render_panel_edit_forum": nil, - "pre_render_panel_settings": nil, - "pre_render_panel_setting": nil, - "pre_render_panel_word_filters": nil, + "pre_render_panel_dashboard": nil, + "pre_render_panel_forums": nil, + "pre_render_panel_delete_forum": nil, + "pre_render_panel_edit_forum": nil, + "pre_render_panel_settings": nil, + "pre_render_panel_setting": nil, + "pre_render_panel_word_filters": nil, "pre_render_panel_word_filters_edit": nil, - "pre_render_panel_plugins": nil, - "pre_render_panel_users": nil, - "pre_render_panel_edit_user": nil, - "pre_render_panel_groups": nil, - "pre_render_panel_edit_group": nil, - "pre_render_panel_edit_group_perms": nil, - "pre_render_panel_themes": nil, - "pre_render_panel_mod_log": nil, + "pre_render_panel_plugins": nil, + "pre_render_panel_users": nil, + "pre_render_panel_edit_user": nil, + "pre_render_panel_groups": nil, + "pre_render_panel_edit_group": nil, + "pre_render_panel_edit_group_perms": nil, + "pre_render_panel_themes": nil, + "pre_render_panel_mod_log": nil, - "pre_render_error": nil, // Note: This hook isn't run for a few errors whose templates are computed at startup and reused, such as InternalError. This hook is also not available in JS mode. + "pre_render_error": nil, // Note: This hook isn't run for a few errors whose templates are computed at startup and reused, such as InternalError. This hook is also not available in JS mode. "pre_render_security_error": nil, } -type Plugin struct -{ - UName string - Name string - Author string - URL string - Settings string - Active bool - Tag string - Type string +type Plugin struct { + UName string + Name string + Author string + URL string + Settings string + Active bool + Tag string + Type string Installable bool - Installed bool + Installed bool - Init func()error - Activate func()error + Init func() error + Activate func() error Deactivate func() - Install func()error - Uninstall func()error + Install func() error + Uninstall func() error Hooks map[string]int } @@ -119,114 +125,111 @@ func LoadPlugins() error { plugin.Installed = installed plugins[uname] = plugin } - err = rows.Err() - if err != nil { - return err - } - return nil + return rows.Err() } -func NewPlugin(uname string, name string, author string, url string, settings string, tag string, ptype string, init func()error, activate func()error, deactivate func(), install func()error, uninstall func()error) *Plugin { +func NewPlugin(uname string, name string, author string, url string, settings string, tag string, ptype string, init func() error, activate func() error, deactivate func(), install func() error, uninstall func() error) *Plugin { return &Plugin{ - UName: uname, - Name: name, - Author: author, - URL: url, - Settings: settings, - Tag: tag, - Type: ptype, + UName: uname, + Name: name, + Author: author, + URL: url, + Settings: settings, + Tag: tag, + Type: ptype, Installable: (install != nil), - Init: init, - Activate: activate, - Deactivate: deactivate, - Install: install, + Init: init, + Activate: activate, + Deactivate: deactivate, + Install: install, //Uninstall: uninstall, /* - 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. + 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, + Active: false, Installed: false, - Hooks: make(map[string]int), + 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(string)string: - if len(sshooks[name]) == 0 { - var hookSlice []func(string)string - hookSlice = append(hookSlice, h) - sshooks[name] = hookSlice - } else { - sshooks[name] = append(sshooks[name], h) - } - plugin.Hooks[name] = len(sshooks[name]) - case func(http.ResponseWriter, *http.Request, *User, interface{})bool: - if len(pre_render_hooks[name]) == 0 { - var hookSlice []func(http.ResponseWriter, *http.Request, *User, interface{})bool - hookSlice = append(hookSlice, h) - pre_render_hooks[name] = hookSlice - } else { - pre_render_hooks[name] = append(pre_render_hooks[name], h) - } - plugin.Hooks[name] = len(pre_render_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()? + 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(string) string: + if len(sshooks[name]) == 0 { + var hookSlice []func(string) string + hookSlice = append(hookSlice, h) + sshooks[name] = hookSlice + } else { + sshooks[name] = append(sshooks[name], h) + } + plugin.Hooks[name] = len(sshooks[name]) + case func(http.ResponseWriter, *http.Request, *User, interface{}) bool: + if len(preRenderHooks[name]) == 0 { + var hookSlice []func(http.ResponseWriter, *http.Request, *User, interface{}) bool + hookSlice = append(hookSlice, h) + preRenderHooks[name] = hookSlice + } else { + preRenderHooks[name] = append(preRenderHooks[name], h) + } + plugin.Hooks[name] = len(preRenderHooks[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] - if len(hook) == 1 { - hook = []func(interface{})interface{}{} - } else { - hook = append(hook[:key], hook[key + 1:]...) - } - hooks[name] = hook - case func(string)string: - key := plugin.Hooks[name] - hook := sshooks[name] - if len(hook) == 1 { - hook = []func(string)string{} - } else { - hook = append(hook[:key], hook[key + 1:]...) - } - sshooks[name] = hook - case func(http.ResponseWriter, *http.Request, *User, interface{})bool: - key := plugin.Hooks[name] - hook := pre_render_hooks[name] - if len(hook) == 1 { - hook = []func(http.ResponseWriter, *http.Request, *User, interface{})bool{} - } else { - hook = append(hook[:key], hook[key + 1:]...) - } - pre_render_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()? + case func(interface{}) interface{}: + key := plugin.Hooks[name] + hook := hooks[name] + if len(hook) == 1 { + hook = []func(interface{}) interface{}{} + } else { + hook = append(hook[:key], hook[key+1:]...) + } + hooks[name] = hook + case func(string) string: + key := plugin.Hooks[name] + hook := sshooks[name] + if len(hook) == 1 { + hook = []func(string) string{} + } else { + hook = append(hook[:key], hook[key+1:]...) + } + sshooks[name] = hook + case func(http.ResponseWriter, *http.Request, *User, interface{}) bool: + key := plugin.Hooks[name] + hook := preRenderHooks[name] + if len(hook) == 1 { + hook = []func(http.ResponseWriter, *http.Request, *User, interface{}) bool{} + } else { + hook = append(hook[:key], hook[key+1:]...) + } + preRenderHooks[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) } -var plugins_inited bool = false -func init_plugins() { +var pluginsInited = false + +func initPlugins() { for name, body := range plugins { log.Print("Added plugin " + name) if body.Active { @@ -241,49 +244,49 @@ func init_plugins() { } } } - plugins_inited = true + pluginsInited = true } -func run_hook(name string, data interface{}) interface{} { +func runHook(name string, data interface{}) interface{} { for _, hook := range hooks[name] { data = hook(data) } return data } -func run_hook_noreturn(name string, data interface{}) { +func runHookNoreturn(name string, data interface{}) { for _, hook := range hooks[name] { _ = hook(data) } } -func run_vhook(name string, data ...interface{}) interface{} { +func runVhook(name string, data ...interface{}) interface{} { return vhooks[name](data...) } -func run_vhook_noreturn(name string, data ...interface{}) { +func runVhookNoreturn(name string, data ...interface{}) { _ = vhooks[name](data...) } // Trying to get a teeny bit of type-safety where-ever possible, especially for such a critical set of hooks -func run_sshook(name string, data string) string { +func runSshook(name string, data string) string { for _, hook := range sshooks[name] { data = hook(data) } return data } -func run_pre_render_hook(name string, w http.ResponseWriter, r *http.Request, user *User, data interface{}) (halt bool) { +func runPreRenderHook(name string, w http.ResponseWriter, r *http.Request, user *User, data interface{}) (halt bool) { // This hook runs on ALL pre_render hooks - for _, hook := range pre_render_hooks["pre_render"] { - if hook(w,r,user,data) { + for _, hook := range preRenderHooks["pre_render"] { + if hook(w, r, user, data) { return true } } // The actual pre_render hook - for _, hook := range pre_render_hooks[name] { - if hook(w,r,user,data) { + for _, hook := range preRenderHooks[name] { + if hook(w, r, user, data) { return true } } diff --git a/files.go b/files.go index 008f8161..92efa373 100644 --- a/files.go +++ b/files.go @@ -1,65 +1,59 @@ package main import ( - "log" "bytes" - "strings" + "log" "mime" + "strings" //"errors" - "os" - "io/ioutil" - "path/filepath" - "net/http" "compress/gzip" + "io/ioutil" + "net/http" + "os" + "path/filepath" ) -type SFile struct -{ - Data []byte - GzipData []byte - Pos int64 - Length int64 - GzipLength int64 - Mimetype string - Info os.FileInfo +type SFile struct { + Data []byte + GzipData []byte + Pos int64 + Length int64 + GzipLength int64 + Mimetype string + Info os.FileInfo FormattedModTime string } -type CssData struct -{ +type CssData struct { ComingSoon string } -func init_static_files() { - log.Print("Loading the static files.") - err := filepath.Walk("./public", func(path string, f os.FileInfo, err error) error { +func initStaticFiles() error { + return filepath.Walk("./public", func(path string, f os.FileInfo, err error) error { if f.IsDir() { return nil } - path = strings.Replace(path,"\\","/",-1) + path = strings.Replace(path, "\\", "/", -1) data, err := ioutil.ReadFile(path) if err != nil { return err } - path = strings.TrimPrefix(path,"public/") - var ext string = filepath.Ext("/public/" + path) - gzip_data := compress_bytes_gzip(data) + path = strings.TrimPrefix(path, "public/") + var ext = filepath.Ext("/public/" + path) + gzipData := compressBytesGzip(data) - static_files["/static/" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(ext),f,f.ModTime().UTC().Format(http.TimeFormat)} + staticFiles["/static/"+path] = SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)} if dev.DebugMode { log.Print("Added the '" + path + "' static file.") } return nil }) - if err != nil { - log.Fatal(err) - } } -func add_static_file(path string, prefix string) error { +func addStaticFile(path string, prefix string) error { data, err := ioutil.ReadFile(path) if err != nil { return err @@ -73,11 +67,11 @@ func add_static_file(path string, prefix string) error { return err } - var ext string = filepath.Ext(path) + var ext = filepath.Ext(path) path = strings.TrimPrefix(path, prefix) - gzip_data := compress_bytes_gzip(data) + gzipData := compressBytesGzip(data) - static_files["/static" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(ext),f,f.ModTime().UTC().Format(http.TimeFormat)} + staticFiles["/static"+path] = SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)} if dev.DebugMode { log.Print("Added the '" + path + "' static file") @@ -85,10 +79,10 @@ func add_static_file(path string, prefix string) error { return nil } -func compress_bytes_gzip(in []byte) []byte { +func compressBytesGzip(in []byte) []byte { var buff bytes.Buffer gz := gzip.NewWriter(&buff) - gz.Write(in) - gz.Close() + _, _ = gz.Write(in) // TO-DO: What if this errors? What circumstances could it error under? Should we add a second return value? + _ = gz.Close() return buff.Bytes() } diff --git a/forum.go b/forum.go index 9e58bbc6..c90e6143 100644 --- a/forum.go +++ b/forum.go @@ -4,51 +4,48 @@ package main import "strconv" import _ "github.com/go-sql-driver/mysql" -type ForumAdmin struct -{ - ID int - Name string - Desc string - Active bool - Preset string +type ForumAdmin struct { + ID int + Name string + Desc string + Active bool + Preset string TopicCount int PresetLang string } -type Forum struct -{ - ID int - Link string - Name string - Desc string - Active bool - Preset string - ParentID int - ParentType string - TopicCount int +type Forum struct { + ID int + Link string + Name string + Desc string + Active bool + Preset string + ParentID int + ParentType string + TopicCount int LastTopicLink string - LastTopic string - LastTopicID int - LastReplyer string + LastTopic string + LastTopicID int + LastReplyer string LastReplyerID int LastTopicTime string } -type ForumSimple struct -{ - ID int - Name string +type ForumSimple struct { + ID int + Name string Active bool Preset string } -func build_forum_url(slug string, fid int) string { +func buildForumUrl(slug string, fid int) string { if slug == "" { return "/forum/" + strconv.Itoa(fid) } return "/forum/" + slug + "." + strconv.Itoa(fid) } -func get_forum_url_prefix() string { +func getForumURLPrefix() string { return "/forum/" } diff --git a/forum_store.go b/forum_store.go index e192c96e..73becf91 100644 --- a/forum_store.go +++ b/forum_store.go @@ -3,17 +3,17 @@ package main import "log" import "sync" + //import "sync/atomic" import "database/sql" import "./query_gen/lib" -var forum_update_mutex sync.Mutex -var forum_create_mutex sync.Mutex -var forum_perms map[int]map[int]ForumPerms // [gid][fid]Perms +var forumUpdateMutex sync.Mutex +var forumCreateMutex sync.Mutex +var forumPerms map[int]map[int]ForumPerms // [gid][fid]Perms var fstore ForumStore -type ForumStore interface -{ +type ForumStore interface { LoadForums() error DirtyGet(id int) *Forum Get(id int) (*Forum, error) @@ -28,63 +28,62 @@ type ForumStore interface CascadeDelete(id int) error IncrementTopicCount(id int) error DecrementTopicCount(id int) error - UpdateLastTopic(topic_name string, tid int, username string, uid int, time string, fid int) error + UpdateLastTopic(topicName string, tid int, username string, uid int, time string, fid int) error Exists(id int) bool - GetAll() ([]*Forum,error) - GetAllIDs() ([]int,error) + GetAll() ([]*Forum, error) + GetAllIDs() ([]int, error) //GetChildren(parentID int, parentType string) ([]*Forum,error) //GetFirstChild(parentID int, parentType string) (*Forum,error) - CreateForum(forum_name string, forum_desc string, active bool, preset string) (int, error) + CreateForum(forumName string, forumDesc string, active bool, preset string) (int, error) GetGlobalCount() int } -type StaticForumStore struct -{ +type StaticForumStore struct { forums []*Forum // The IDs for a forum tend to be low and sequential for the most part, so we can get more performance out of using a slice instead of a map AND it has better concurrency //fids []int forumCapCount int - get *sql.Stmt - get_all *sql.Stmt - forum_count *sql.Stmt + get *sql.Stmt + getAll *sql.Stmt + forumCount *sql.Stmt } func NewStaticForumStore() *StaticForumStore { - get_stmt, err := qgen.Builder.SimpleSelect("forums","name, desc, active, preset, parentID, parentType, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime","fid = ?","","") + getStmt, err := qgen.Builder.SimpleSelect("forums", "name, desc, active, preset, parentID, parentType, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime", "fid = ?", "", "") if err != nil { log.Fatal(err) } - get_all_stmt, err := qgen.Builder.SimpleSelect("forums","fid, name, desc, active, preset, parentID, parentType, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime","","fid ASC","") + getAllStmt, err := qgen.Builder.SimpleSelect("forums", "fid, name, desc, active, preset, parentID, parentType, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime", "", "fid ASC", "") if err != nil { log.Fatal(err) } - forum_count_stmt, err := qgen.Builder.SimpleCount("forums","name != ''","") + forumCountStmt, err := qgen.Builder.SimpleCount("forums", "name != ''", "") if err != nil { log.Fatal(err) } return &StaticForumStore{ - get: get_stmt, - get_all: get_all_stmt, - forum_count: forum_count_stmt, + get: getStmt, + getAll: getAllStmt, + forumCount: forumCountStmt, } } func (sfs *StaticForumStore) LoadForums() error { log.Print("Adding the uncategorised forum") - var forums []*Forum = []*Forum{ - &Forum{0,build_forum_url(name_to_slug("Uncategorised"),0),"Uncategorised","",config.UncategorisedForumVisible,"all",0,"",0,"","",0,"",0,""}, + var forums = []*Forum{ + &Forum{0, buildForumUrl(nameToSlug("Uncategorised"), 0), "Uncategorised", "", config.UncategorisedForumVisible, "all", 0, "", 0, "", "", 0, "", 0, ""}, } - rows, err := get_forums_stmt.Query() + rows, err := get_forums_stmt.Query() if err != nil { return err } defer rows.Close() - var i int = 1 - for ;rows.Next();i++ { - forum := Forum{ID:0,Active:true,Preset:"all"} + var i = 1 + for ; rows.Next(); i++ { + forum := Forum{ID: 0, Active: true, Preset: "all"} err = rows.Scan(&forum.ID, &forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.ParentID, &forum.ParentType, &forum.TopicCount, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime) if err != nil { return err @@ -93,7 +92,7 @@ func (sfs *StaticForumStore) LoadForums() error { // Ugh, you really shouldn't physically delete these items, it makes a big mess of things if forum.ID != i { log.Print("Stop physically deleting forums. You are messing up the IDs. Use the Forum Manager or delete_forum() instead x.x") - sfs.fill_forum_id_gap(i, forum.ID) + sfs.fillForumIDGap(i, forum.ID) } if forum.Name == "" { @@ -104,9 +103,9 @@ func (sfs *StaticForumStore) LoadForums() error { log.Print("Adding the " + forum.Name + " forum") } - forum.Link = build_forum_url(name_to_slug(forum.Name),forum.ID) - forum.LastTopicLink = build_topic_url(name_to_slug(forum.LastTopic),forum.LastTopicID) - forums = append(forums,&forum) + forum.Link = buildForumUrl(nameToSlug(forum.Name), forum.ID) + forum.LastTopicLink = buildTopicURL(nameToSlug(forum.LastTopic), forum.LastTopicID) + forums = append(forums, &forum) } err = rows.Err() if err != nil { @@ -120,7 +119,7 @@ func (sfs *StaticForumStore) LoadForums() error { func (sfs *StaticForumStore) DirtyGet(id int) *Forum { if !((id <= sfs.forumCapCount) && (id >= 0) && sfs.forums[id].Name != "") { - return &Forum{ID:-1,Name:""} + return &Forum{ID: -1, Name: ""} } return sfs.forums[id] } @@ -147,16 +146,13 @@ func (sfs *StaticForumStore) CascadeGetCopy(id int) (forum Forum, err error) { } func (sfs *StaticForumStore) BypassGet(id int) (*Forum, error) { - var forum Forum = Forum{ID:id} + var forum = Forum{ID: id} err := sfs.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.TopicCount, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime) - if err != nil { - return nil, err - } - return &forum, nil + return &forum, err } func (sfs *StaticForumStore) Load(id int) error { - var forum Forum = Forum{ID:id} + var forum = Forum{ID: id} err := sfs.get.QueryRow(id).Scan(&forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.TopicCount, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime) if err != nil { return err @@ -167,17 +163,17 @@ func (sfs *StaticForumStore) Load(id int) error { // TO-DO: Set should be able to add new indices not just replace existing ones for consistency with UserStore and TopicStore func (sfs *StaticForumStore) Set(forum *Forum) error { - forum_update_mutex.Lock() + forumUpdateMutex.Lock() if !sfs.Exists(forum.ID) { - forum_update_mutex.Unlock() + forumUpdateMutex.Unlock() return ErrNoRows } sfs.forums[forum.ID] = forum - forum_update_mutex.Unlock() + forumUpdateMutex.Unlock() return nil } -func (sfs *StaticForumStore) GetAll() ([]*Forum,error) { +func (sfs *StaticForumStore) GetAll() ([]*Forum, error) { return sfs.forums, nil } @@ -191,9 +187,9 @@ func (sfs *StaticForumStore) GetFirstChild(parentID int, parentType string) (*Fo // We can cheat slightly, as the StaticForumStore has all the IDs under the cap ;) // Should we cache this? Well, it's only really used for superadmins right now. -func (sfs *StaticForumStore) GetAllIDs() ([]int,error) { - var max int = sfs.forumCapCount - var ids []int = make([]int,max) +func (sfs *StaticForumStore) GetAllIDs() ([]int, error) { + var max = sfs.forumCapCount + var ids = make([]int, max) for i := 0; i < max; i++ { ids[i] = i } @@ -205,13 +201,13 @@ func (sfs *StaticForumStore) Exists(id int) bool { } func (sfs *StaticForumStore) Delete(id int) error { - forum_update_mutex.Lock() + forumUpdateMutex.Lock() if !sfs.Exists(id) { - forum_update_mutex.Unlock() + forumUpdateMutex.Unlock() return nil } sfs.forums[id].Name = "" - forum_update_mutex.Unlock() + forumUpdateMutex.Unlock() return nil } @@ -221,13 +217,13 @@ func (sfs *StaticForumStore) CascadeDelete(id int) error { return err } - forum_update_mutex.Lock() + forumUpdateMutex.Lock() _, err = delete_forum_stmt.Exec(id) if err != nil { return err } forum.Name = "" - forum_update_mutex.Unlock() + forumUpdateMutex.Unlock() return nil } @@ -236,11 +232,11 @@ func (sfs *StaticForumStore) IncrementTopicCount(id int) error { if err != nil { return err } - _, err = add_topics_to_forum_stmt.Exec(1,id) + _, err = add_topics_to_forum_stmt.Exec(1, id) if err != nil { return err } - forum.TopicCount += 1 + forum.TopicCount++ return nil } @@ -253,7 +249,7 @@ func (sfs *StaticForumStore) DecrementTopicCount(id int) error { if err != nil { return err } - forum.TopicCount -= 1 + forum.TopicCount-- return nil } @@ -264,7 +260,7 @@ func (sfs *StaticForumStore) UpdateLastTopic(topic_name string, tid int, usernam return err } - _, err = update_forum_cache_stmt.Exec(topic_name,tid,username,uid,fid) + _, err = update_forum_cache_stmt.Exec(topic_name, tid, username, uid, fid) if err != nil { return err } @@ -278,15 +274,15 @@ func (sfs *StaticForumStore) UpdateLastTopic(topic_name string, tid int, usernam return nil } -func (sfs *StaticForumStore) CreateForum(forum_name string, forum_desc string, active bool, preset string) (int, error) { +func (sfs *StaticForumStore) CreateForum(forumName string, forumDesc string, active bool, preset string) (int, error) { var fid int err := forum_entry_exists_stmt.QueryRow().Scan(&fid) if err != nil && err != ErrNoRows { return 0, err } if err != ErrNoRows { - forum_update_mutex.Lock() - _, err = update_forum_stmt.Exec(forum_name, forum_desc, active, preset, fid) + forumUpdateMutex.Lock() + _, err = update_forum_stmt.Exec(forumName, forumDesc, active, preset, fid) if err != nil { return fid, err } @@ -294,16 +290,16 @@ func (sfs *StaticForumStore) CreateForum(forum_name string, forum_desc string, a if err != nil { return 0, ErrCacheDesync } - forum.Name = forum_name - forum.Desc = forum_desc + forum.Name = forumName + forum.Desc = forumDesc forum.Active = active forum.Preset = preset - forum_update_mutex.Unlock() + forumUpdateMutex.Unlock() return fid, nil } - forum_create_mutex.Lock() - res, err := create_forum_stmt.Exec(forum_name, forum_desc, active, preset) + forumCreateMutex.Lock() + res, err := create_forum_stmt.Exec(forumName, forumDesc, active, preset) if err != nil { return 0, err } @@ -314,27 +310,26 @@ func (sfs *StaticForumStore) CreateForum(forum_name string, forum_desc string, a } fid = int(fid64) - sfs.forums = append(sfs.forums, &Forum{fid,build_forum_url(name_to_slug(forum_name),fid),forum_name,forum_desc,active,preset,0,"",0,"","",0,"",0,""}) + sfs.forums = append(sfs.forums, &Forum{fid, buildForumUrl(nameToSlug(forumName), fid), forumName, forumDesc, active, preset, 0, "", 0, "", "", 0, "", 0, ""}) sfs.forumCapCount++ // TO-DO: Add a GroupStore. How would it interact with the ForumStore? - permmap_to_query(preset_to_permmap(preset),fid) - forum_create_mutex.Unlock() + permmapToQuery(presetToPermmap(preset), fid) + forumCreateMutex.Unlock() return fid, nil } -func (sfs *StaticForumStore) fill_forum_id_gap(biggerID int, smallerID int) { - dummy := Forum{ID:0,Name:"",Active:false,Preset:"all"} +func (sfs *StaticForumStore) fillForumIDGap(biggerID int, smallerID int) { + dummy := Forum{ID: 0, Name: "", Active: false, Preset: "all"} for i := smallerID; i > biggerID; i++ { sfs.forums = append(sfs.forums, &dummy) } } -// Return the total number of forums // TO-DO: Get the total count of forums in the forum store minus the blanked forums rather than doing a heavy query for this? -func (sfs *StaticForumStore) GetGlobalCount() int { - var fcount int - err := sfs.forum_count.QueryRow().Scan(&fcount) +// GetGlobalCount returns the total number of forums +func (sfs *StaticForumStore) GetGlobalCount() (fcount int) { + err := sfs.forumCount.QueryRow().Scan(&fcount) if err != nil { LogError(err) } diff --git a/gen_mysql.go b/gen_mysql.go index d408f37b..481dc247 100644 --- a/gen_mysql.go +++ b/gen_mysql.go @@ -7,6 +7,7 @@ package main import "log" import "database/sql" +// nolint var get_user_stmt *sql.Stmt var get_reply_stmt *sql.Stmt var get_user_reply_stmt *sql.Stmt @@ -123,6 +124,7 @@ var add_forum_perms_to_forum_staff_stmt *sql.Stmt var add_forum_perms_to_forum_members_stmt *sql.Stmt var notify_watchers_stmt *sql.Stmt +// nolint func _gen_mysql() (err error) { if dev.DebugMode { log.Print("Building the generated statements") diff --git a/gen_pgsql.go b/gen_pgsql.go index f0496d04..697778ee 100644 --- a/gen_pgsql.go +++ b/gen_pgsql.go @@ -6,6 +6,7 @@ package main import "log" import "database/sql" +// nolint var add_replies_to_topic_stmt *sql.Stmt var remove_replies_from_topic_stmt *sql.Stmt var add_topics_to_forum_stmt *sql.Stmt @@ -46,6 +47,7 @@ var verify_email_stmt *sql.Stmt var set_temp_group_stmt *sql.Stmt var update_word_filter_stmt *sql.Stmt +// nolint func _gen_pgsql() (err error) { if dev.DebugMode { log.Print("Building the generated statements") diff --git a/gen_router.go b/gen_router.go index e5c5115e..53b7d4f9 100644 --- a/gen_router.go +++ b/gen_router.go @@ -169,7 +169,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) { route_panel_themes(w,req,user) return case "/panel/themes/default/": - route_panel_themes_default(w,req,user,extra_data) + route_panel_themes_set_default(w,req,user,extra_data) return case "/panel/plugins/": route_panel_plugins(w,req,user) diff --git a/general_test.go b/general_test.go index f6135b5a..d9e0ae3b 100644 --- a/general_test.go +++ b/general_test.go @@ -2,56 +2,52 @@ package main import ( //"os" - "log" "bytes" - "strings" + "log" "strconv" + "strings" //"math/rand" - "testing" - "time" + "database/sql" "net/http" "net/http/httptest" - "html/template" - "io/ioutil" - "database/sql" + "testing" + "time" //"runtime/pprof" - //_ "github.com/go-sql-driver/mysql" //"github.com/erikstmartin/go-testdb" //"github.com/husobee/vestigo" ) -var db_test *sql.DB -var db_prod *sql.DB +var dbTest *sql.DB +var dbProd *sql.DB var gloinited bool func gloinit() error { dev.DebugMode = false //nogrouplog = true - // init_database is a little noisy for a benchmark - //discard := ioutil.Discard - //log.SetOutput(discard) - startTime = time.Now() - //timeLocation = startTime.Location() - process_config() + processConfig() - init_themes() - err := init_database() + err := initThemes() if err != nil { return err } - db_prod = db + err = initDatabase() + if err != nil { + return err + } + + dbProd = db //db_test, err = sql.Open("testdb","") //if err != nil { // return err //} - init_templates() - db_prod.SetMaxOpenConns(64) - err = init_errors() + initTemplates() + dbProd.SetMaxOpenConns(64) + err = initErrors() if err != nil { return err } @@ -64,11 +60,14 @@ func gloinit() error { topics = NewSqlTopicStore() } - init_static_files() - //log.SetOutput(os.Stdout) + log.Print("Loading the static files.") + err = initStaticFiles() + if err != nil { + return err + } auth = NewDefaultAuth() - err = init_word_filters() + err = initWordFilters() if err != nil { return err } @@ -79,182 +78,20 @@ func gloinit() error { } func init() { - gloinit() -} - -func BenchmarkTopicTemplateSerial(b *testing.B) { - b.ReportAllocs() - - user := User{0,"bob","Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,make(map[string]bool),"",false,"","","","","",0,0,"127.0.0.1"} - admin := User{1,"admin-alice","Admin Alice","admin@localhost",0,true,true,true,true,true,false,AllPerms,make(map[string]bool),"",false,"","","","","",-1,58,"127.0.0.1"} - - topic := TopicUser{Title: "Lol",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",ClassName: "",Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"} - - var replyList []Reply - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry","Jerry",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry2","Jerry2",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry3","Jerry3",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry4","Jerry4",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry5","Jerry5",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry6","Jerry6",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry7","Jerry7",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry8","Jerry8",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry9","Jerry9",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry10","Jerry10",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) - - headerVars := HeaderVars{ - NoticeList:[]string{"test"}, - Stylesheets:[]string{"panel"}, - Scripts:[]string{"whatever"}, - Widgets:PageWidgets{ - LeftSidebar: template.HTML("lalala"), - }, - Site:site, - } - - tpage := TopicPage{"Topic Blah",user,headerVars,replyList,topic,1,1,extData} - tpage2 := TopicPage{"Topic Blah",admin,headerVars,replyList,topic,1,1,extData} - w := ioutil.Discard - - b.Run("compiled_useradmin", func(b *testing.B) { - for i := 0; i < b.N; i++ { - template_topic(tpage2,w) - } - }) - b.Run("interpreted_useradmin", func(b *testing.B) { - for i := 0; i < b.N; i++ { - templates.ExecuteTemplate(w,"topic.html", tpage2) - } - }) - b.Run("compiled_userguest", func(b *testing.B) { - for i := 0; i < b.N; i++ { - template_topic(tpage,w) - } - }) - b.Run("interpreted_userguest", func(b *testing.B) { - for i := 0; i < b.N; i++ { - templates.ExecuteTemplate(w,"topic.html", tpage) - } - }) - - w2 := httptest.NewRecorder() - b.Run("compiled_useradmin_recorder", func(b *testing.B) { - for i := 0; i < b.N; i++ { - w2.Body.Reset() - template_topic(tpage2,w2) - } - }) - b.Run("interpreted_useradmin_recorder", func(b *testing.B) { - for i := 0; i < b.N; i++ { - w2.Body.Reset() - templates.ExecuteTemplate(w2,"topic.html", tpage2) - } - }) - b.Run("compiled_userguest_recorder", func(b *testing.B) { - for i := 0; i < b.N; i++ { - w2.Body.Reset() - template_topic(tpage,w2) - } - }) - b.Run("interpreted_userguest_recorder", func(b *testing.B) { - for i := 0; i < b.N; i++ { - w2.Body.Reset() - templates.ExecuteTemplate(w2,"topic.html", tpage) - } - }) - - /*f, err := os.Create("topic_bench.prof") + err := gloinit() if err != nil { log.Fatal(err) } - pprof.StartCPUProfile(f) - defer pprof.StopCPUProfile()*/ -} - -func BenchmarkTopicsTemplateSerial(b *testing.B) { - b.ReportAllocs() - - user := User{0,build_profile_url("bob",0),"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,make(map[string]bool),"",false,"","","","","",0,0,"127.0.0.1"} - admin := User{1,build_profile_url("admin-alice",1),"Admin Alice","admin@localhost",0,true,true,true,true,true,false,AllPerms,make(map[string]bool),"",false,"","","","","Admin",58,580,"127.0.0.1"} - - var topicList []*TopicsRow - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - topicList = append(topicList, &TopicsRow{Title: "Hey everyone!",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,Creator:&admin,LastUser:&user,ClassName:"", IpAddress: "127.0.0.1"}) - - headerVars := HeaderVars{ - NoticeList:[]string{"test"}, - Stylesheets:[]string{"panel"}, - Scripts:[]string{"whatever"}, - Widgets:PageWidgets{ - LeftSidebar: template.HTML("lalala"), - }, - Site:site, - } - - w := ioutil.Discard - tpage := TopicsPage{"Topic Blah",user,headerVars,topicList,extData} - tpage2 := TopicsPage{"Topic Blah",admin,headerVars,topicList,extData} - - b.Run("compiled_useradmin", func(b *testing.B) { - for i := 0; i < b.N; i++ { - template_topics(tpage2,w) - } - }) - b.Run("interpreted_useradmin",func(b *testing.B) { - for i := 0; i < b.N; i++ { - templates.ExecuteTemplate(w,"topics.html", tpage2) - } - }) - b.Run("compiled_userguest",func(b *testing.B) { - for i := 0; i < b.N; i++ { - template_topics(tpage,w) - } - }) - b.Run("interpreted_userguest",func(b *testing.B) { - for i := 0; i < b.N; i++ { - templates.ExecuteTemplate(w,"topics.html", tpage) - } - }) -} - -func BenchmarkStaticRouteParallel(b *testing.B) { - b.ReportAllocs() - if !gloinited { - gloinit() - } - if !plugins_inited { - init_plugins() - } - - b.RunParallel(func(pb *testing.PB) { - static_w := httptest.NewRecorder() - static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil)) - static_handler := http.HandlerFunc(route_static) - for pb.Next() { - //static_w.Code = 200 - static_w.Body.Reset() - static_handler.ServeHTTP(static_w,static_req) - //if static_w.Code != 200 { - // pb.Print(static_w.Body) - // panic("HTTP Error!") - //} - } - }) } // TO-DO: Swap out LocalError for a panic for this? func BenchmarkTopicAdminRouteParallel(b *testing.B) { b.ReportAllocs() if !gloinited { - gloinit() + err := gloinit() + if err != nil { + b.Fatal(err) + } } b.RunParallel(func(pb *testing.PB) { @@ -262,27 +99,27 @@ func BenchmarkTopicAdminRouteParallel(b *testing.B) { if err != nil { b.Fatal(err) } - if !admin.Is_Admin { + if !admin.IsAdmin { b.Fatal("UID1 is not an admin") } - admin_uid_cookie := http.Cookie{Name:"uid",Value:"1",Path:"/",MaxAge: year} - admin_session_cookie := http.Cookie{Name:"session",Value: admin.Session,Path:"/",MaxAge: year} + adminUIDCookie := http.Cookie{Name: "uid", Value: "1", Path: "/", MaxAge: year} + adminSessionCookie := http.Cookie{Name: "session", Value: admin.Session, Path: "/", MaxAge: year} - topic_w := httptest.NewRecorder() - topic_req := httptest.NewRequest("get","/topic/1",bytes.NewReader(nil)) - topic_req_admin := topic_req - topic_req_admin.AddCookie(&admin_uid_cookie) - topic_req_admin.AddCookie(&admin_session_cookie) + topicW := httptest.NewRecorder() + topicReq := httptest.NewRequest("get", "/topic/1", bytes.NewReader(nil)) + topicReqAdmin := topicReq + topicReqAdmin.AddCookie(&adminUIDCookie) + topicReqAdmin.AddCookie(&adminSessionCookie) // Deal with the session stuff, etc. - user, ok := PreRoute(topic_w,topic_req_admin) + user, ok := PreRoute(topicW, topicReqAdmin) if !ok { b.Fatal("Mysterious error!") } for pb.Next() { - topic_w.Body.Reset() - route_topic_id(topic_w,topic_req_admin,user) + topicW.Body.Reset() + route_topic_id(topicW, topicReqAdmin, user) } }) } @@ -290,15 +127,18 @@ func BenchmarkTopicAdminRouteParallel(b *testing.B) { func BenchmarkTopicGuestRouteParallel(b *testing.B) { b.ReportAllocs() if !gloinited { - gloinit() + err := gloinit() + if err != nil { + b.Fatal(err) + } } b.RunParallel(func(pb *testing.PB) { - topic_w := httptest.NewRecorder() - topic_req := httptest.NewRequest("get","/topic/1",bytes.NewReader(nil)) + topicW := httptest.NewRecorder() + topicReq := httptest.NewRequest("get", "/topic/1", bytes.NewReader(nil)) for pb.Next() { - topic_w.Body.Reset() - route_topic_id(topic_w,topic_req,guest_user) + topicW.Body.Reset() + route_topic_id(topicW, topicReq, guestUser) } }) } @@ -628,13 +468,16 @@ func BenchmarkForumsGuestRouteParallel(b *testing.B) { func BenchmarkQueryTopicParallel(b *testing.B) { b.ReportAllocs() if !gloinited { - gloinit() + err := gloinit() + if err != nil { + b.Fatal(err) + } } b.RunParallel(func(pb *testing.PB) { var tu TopicUser for pb.Next() { - err := db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?", 1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.Is_Closed, &tu.Sticky, &tu.ParentID, &tu.IpAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) + err := db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?", 1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) if err == ErrNoRows { log.Fatal("No rows found!") return @@ -649,13 +492,16 @@ func BenchmarkQueryTopicParallel(b *testing.B) { func BenchmarkQueryPreparedTopicParallel(b *testing.B) { b.ReportAllocs() if !gloinited { - gloinit() + err := gloinit() + if err != nil { + b.Fatal(err) + } } b.RunParallel(func(pb *testing.PB) { var tu TopicUser for pb.Next() { - err := get_topic_user_stmt.QueryRow(1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.Is_Closed, &tu.Sticky, &tu.ParentID, &tu.IpAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) + err := get_topic_user_stmt.QueryRow(1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) if err == ErrNoRows { b.Fatal("No rows found!") return @@ -672,7 +518,7 @@ func BenchmarkQueriesSerial(b *testing.B) { var tu TopicUser b.Run("topic", func(b *testing.B) { for i := 0; i < b.N; i++ { - err := db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?", 1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.Is_Closed, &tu.Sticky, &tu.ParentID, &tu.IpAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) + err := db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?", 1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) if err == ErrNoRows { b.Fatal("No rows found!") return @@ -691,7 +537,8 @@ func BenchmarkQueriesSerial(b *testing.B) { } defer rows.Close() - for rows.Next() {} + for rows.Next() { + } err = rows.Err() if err != nil { b.Fatal(err) @@ -701,7 +548,7 @@ func BenchmarkQueriesSerial(b *testing.B) { }) var replyItem Reply - var is_super_admin bool + var isSuperAdmin bool var group int b.Run("topic_replies_scan", func(b *testing.B) { for i := 0; i < b.N; i++ { @@ -711,7 +558,7 @@ func BenchmarkQueriesSerial(b *testing.B) { return } for rows.Next() { - err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &is_super_admin, &group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IpAddress) + err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &isSuperAdmin, &group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IPAddress) if err != nil { b.Fatal(err) return @@ -1059,32 +906,32 @@ func BenchmarkParserSerial(b *testing.B) { b.ReportAllocs() b.Run("empty_post", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = parse_message("") + _ = parseMessage("") } }) b.Run("short_post", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = parse_message("Hey everyone, how's it going?") + _ = parseMessage("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? :)") + _ = parseMessage("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? :):):):):)") + _ = parseMessage("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? :):):):):):):):):):)") + _ = parseMessage("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? :):):):):):):):):):):):):):):):):):):):)") + _ = parseMessage("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") } }) } @@ -1093,47 +940,47 @@ func BenchmarkBBCodePluginWithRegexpSerial(b *testing.B) { b.ReportAllocs() b.Run("empty_post", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_regex_parse("") + _ = bbcodeRegexParse("") } }) b.Run("short_post", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_regex_parse("Hey everyone, how's it going?") + _ = bbcodeRegexParse("Hey everyone, how's it going?") } }) b.Run("one_smily", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_regex_parse("Hey everyone, how's it going? :)") + _ = bbcodeRegexParse("Hey everyone, how's it going? :)") } }) b.Run("five_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_regex_parse("Hey everyone, how's it going? :):):):):)") + _ = bbcodeRegexParse("Hey everyone, how's it going? :):):):):)") } }) b.Run("ten_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_regex_parse("Hey everyone, how's it going? :):):):):):):):):):)") + _ = bbcodeRegexParse("Hey everyone, how's it going? :):):):):):):):):):)") } }) b.Run("twenty_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_regex_parse("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") + _ = bbcodeRegexParse("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") } }) b.Run("one_bold", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_regex_parse("[b]H[/b]ey everyone, how's it going?") + _ = bbcodeRegexParse("[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_regex_parse("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") + _ = bbcodeRegexParse("[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_regex_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?") + _ = bbcodeRegexParse("[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?") } }) } @@ -1142,47 +989,47 @@ func BenchmarkBBCodePluginWithoutCodeTagSerial(b *testing.B) { b.ReportAllocs() b.Run("empty_post", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_parse_without_code("") + _ = bbcodeParseWithoutCode("") } }) b.Run("short_post", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_parse_without_code("Hey everyone, how's it going?") + _ = bbcodeParseWithoutCode("Hey everyone, how's it going?") } }) b.Run("one_smily", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_parse_without_code("Hey everyone, how's it going? :)") + _ = bbcodeParseWithoutCode("Hey everyone, how's it going? :)") } }) b.Run("five_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_parse_without_code("Hey everyone, how's it going? :):):):):)") + _ = bbcodeParseWithoutCode("Hey everyone, how's it going? :):):):):)") } }) b.Run("ten_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_parse_without_code("Hey everyone, how's it going? :):):):):):):):):):)") + _ = bbcodeParseWithoutCode("Hey everyone, how's it going? :):):):):):):):):):)") } }) b.Run("twenty_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_parse_without_code("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") + _ = bbcodeParseWithoutCode("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") } }) b.Run("one_bold", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_parse_without_code("[b]H[/b]ey everyone, how's it going?") + _ = bbcodeParseWithoutCode("[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_without_code("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") + _ = bbcodeParseWithoutCode("[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_without_code("[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?") + _ = bbcodeParseWithoutCode("[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?") } }) } @@ -1191,47 +1038,47 @@ func BenchmarkBBCodePluginWithFullParserSerial(b *testing.B) { b.ReportAllocs() b.Run("empty_post", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_full_parse("") + _ = bbcodeFullParse("") } }) b.Run("short_post", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_full_parse("Hey everyone, how's it going?") + _ = bbcodeFullParse("Hey everyone, how's it going?") } }) b.Run("one_smily", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_full_parse("Hey everyone, how's it going? :)") + _ = bbcodeFullParse("Hey everyone, how's it going? :)") } }) b.Run("five_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_full_parse("Hey everyone, how's it going? :):):):):)") + _ = bbcodeFullParse("Hey everyone, how's it going? :):):):):)") } }) b.Run("ten_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_full_parse("Hey everyone, how's it going? :):):):):):):):):):)") + _ = bbcodeFullParse("Hey everyone, how's it going? :):):):):):):):):):)") } }) b.Run("twenty_smilies", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_full_parse("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") + _ = bbcodeFullParse("Hey everyone, how's it going? :):):):):):):):):):):):):):):):):):):):)") } }) b.Run("one_bold", func(b *testing.B) { for i := 0; i < b.N; i++ { - _ = bbcode_full_parse("[b]H[/b]ey everyone, how's it going?") + _ = bbcodeFullParse("[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_full_parse("[b]H[/b][b]e[/b][b]y[/b] [b]e[/b][b]v[/b]eryone, how's it going?") + _ = bbcodeFullParse("[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_full_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?") + _ = bbcodeFullParse("[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?") } }) } @@ -1450,28 +1297,28 @@ func TestForumsGuestRoute(t *testing.T) { }*/ func TestSplittyThing(t *testing.T) { - var extra_data string - var path string = "/pages/hohoho" - t.Log("Raw Path:",path) - if path[len(path) - 1] != '/' { - extra_data = path[strings.LastIndexByte(path,'/') + 1:] - path = path[:strings.LastIndexByte(path,'/') + 1] + var extraData string + var path = "/pages/hohoho" + t.Log("Raw Path:", path) + if path[len(path)-1] != '/' { + extraData = path[strings.LastIndexByte(path, '/')+1:] + path = path[:strings.LastIndexByte(path, '/')+1] } t.Log("Path:", path) - t.Log("Extra Data:", extra_data) + t.Log("Extra Data:", extraData) t.Log("Path Bytes:", []byte(path)) - t.Log("Extra Data Bytes:", []byte(extra_data)) + t.Log("Extra Data Bytes:", []byte(extraData)) t.Log("Splitty thing test") path = "/topics/" - extra_data = "" - t.Log("Raw Path:",path) - if path[len(path) - 1] != '/' { - extra_data = path[strings.LastIndexByte(path,'/') + 1:] - path = path[:strings.LastIndexByte(path,'/') + 1] + extraData = "" + t.Log("Raw Path:", path) + if path[len(path)-1] != '/' { + extraData = path[strings.LastIndexByte(path, '/')+1:] + path = path[:strings.LastIndexByte(path, '/')+1] } t.Log("Path:", path) - t.Log("Extra Data:", extra_data) + t.Log("Extra Data:", extraData) t.Log("Path Bytes:", []byte(path)) - t.Log("Extra Data Bytes:", []byte(extra_data)) + t.Log("Extra Data Bytes:", []byte(extraData)) } diff --git a/group.go b/group.go index 62745124..e9c4c6b0 100644 --- a/group.go +++ b/group.go @@ -3,65 +3,64 @@ package main import "sync" import "encoding/json" -var group_update_mutex sync.Mutex +var groupUpdateMutex sync.Mutex -type GroupAdmin struct -{ - ID int - Name string - Rank string +type GroupAdmin struct { + ID int + Name string + Rank string RankClass string - CanEdit bool + CanEdit bool CanDelete bool } -type Group struct -{ - ID int - Name string - Is_Mod bool - Is_Admin bool - Is_Banned bool - Tag string - Perms Perms +type Group struct { + ID int + Name string + IsMod bool + IsAdmin bool + IsBanned bool + Tag string + Perms Perms PermissionsText []byte - PluginPerms map[string]bool // Custom permissions defined by plugins. What if two plugins declare the same permission, but they handle them in incompatible ways? Very unlikely, we probably don't need to worry about this, the plugin authors should be aware of each other to some extent + PluginPerms map[string]bool // Custom permissions defined by plugins. What if two plugins declare the same permission, but they handle them in incompatible ways? Very unlikely, we probably don't need to worry about this, the plugin authors should be aware of each other to some extent PluginPermsText []byte - Forums []ForumPerms - CanSee []int // The IDs of the forums this group can see + Forums []ForumPerms + CanSee []int // The IDs of the forums this group can see } -var group_create_mutex sync.Mutex -func create_group(group_name string, tag string, is_admin bool, is_mod bool, is_banned bool) (int, error) { +var groupCreateMutex sync.Mutex + +func createGroup(groupName string, tag string, isAdmin bool, isMod bool, isBanned bool) (int, error) { var gid int err := group_entry_exists_stmt.QueryRow().Scan(&gid) if err != nil && err != ErrNoRows { return 0, err } if err != ErrNoRows { - group_update_mutex.Lock() - _, err = update_group_rank_stmt.Exec(is_admin, is_mod, is_banned, gid) + groupUpdateMutex.Lock() + _, err = update_group_rank_stmt.Exec(isAdmin, isMod, isBanned, gid) if err != nil { return gid, err } - _, err = update_group_stmt.Exec(group_name, tag, gid) + _, err = update_group_stmt.Exec(groupName, tag, gid) if err != nil { return gid, err } - groups[gid].Name = group_name + groups[gid].Name = groupName groups[gid].Tag = tag - groups[gid].Is_Banned = is_banned - groups[gid].Is_Mod = is_mod - groups[gid].Is_Admin = is_admin + groups[gid].IsBanned = isBanned + groups[gid].IsMod = isMod + groups[gid].IsAdmin = isAdmin - group_update_mutex.Unlock() + groupUpdateMutex.Unlock() return gid, nil } - group_create_mutex.Lock() - var permstr string = "{}" - res, err := create_group_stmt.Exec(group_name, tag, is_admin, is_mod, is_banned, permstr) + groupCreateMutex.Lock() + var permstr = "{}" + res, err := create_group_stmt.Exec(groupName, tag, isAdmin, isMod, isBanned, permstr) if err != nil { return 0, err } @@ -72,17 +71,17 @@ func create_group(group_name string, tag string, is_admin bool, is_mod bool, is_ } gid = int(gid64) - var perms Perms = BlankPerms + var perms = BlankPerms var blankForums []ForumPerms var blankIntList []int - var plugin_perms map[string]bool = make(map[string]bool) - var plugin_perms_bytes []byte = []byte("{}") + var pluginPerms = make(map[string]bool) + var pluginPermsBytes = []byte("{}") if vhooks["create_group_preappend"] != nil { - run_vhook("create_group_preappend", &plugin_perms, &plugin_perms_bytes) + runVhook("create_group_preappend", &pluginPerms, &pluginPermsBytes) } - groups = append(groups, Group{gid,group_name,is_mod,is_admin,is_banned,tag,perms,[]byte(permstr),plugin_perms,plugin_perms_bytes,blankForums,blankIntList}) - group_create_mutex.Unlock() + groups = append(groups, Group{gid, groupName, isMod, isAdmin, isBanned, tag, perms, []byte(permstr), pluginPerms, pluginPermsBytes, blankForums, blankIntList}) + groupCreateMutex.Unlock() // Generate the forum permissions based on the presets... fdata, err := fstore.GetAll() @@ -90,20 +89,20 @@ func create_group(group_name string, tag string, is_admin bool, is_mod bool, is_ return 0, err } - permupdate_mutex.Lock() + permUpdateMutex.Lock() for _, forum := range fdata { var thePreset string - if is_admin { + if isAdmin { thePreset = "admins" - } else if is_mod { + } else if isMod { thePreset = "staff" - } else if is_banned { + } else if isBanned { thePreset = "banned" } else { thePreset = "members" } - permmap := preset_to_permmap(forum.Preset) + permmap := presetToPermmap(forum.Preset) permitem := permmap[thePreset] permitem.Overrides = true permstr, err := json.Marshal(permitem) @@ -111,20 +110,20 @@ func create_group(group_name string, tag string, is_admin bool, is_mod bool, is_ return gid, err } perms := string(permstr) - _, err = add_forum_perms_to_group_stmt.Exec(gid,forum.ID,forum.Preset,perms) + _, err = add_forum_perms_to_group_stmt.Exec(gid, forum.ID, forum.Preset, perms) if err != nil { return gid, err } - err = rebuild_forum_permissions(forum.ID) + err = rebuildForumPermissions(forum.ID) if err != nil { return gid, err } } - permupdate_mutex.Unlock() + permUpdateMutex.Unlock() return gid, nil } -func group_exists(gid int) bool { +func groupExists(gid int) bool { return (gid <= groupCapCount) && (gid > 0) && groups[gid].Name != "" } diff --git a/install/install.go b/install/install.go index 56dec0a8..bc02196e 100644 --- a/install/install.go +++ b/install/install.go @@ -1,40 +1,47 @@ -/* Copyright Azareal 2017 - 2018 */ +/* +* +* Gosora Installer +* Copyright Azareal 2017 - 2018 +* + */ package main import ( + "bufio" + "database/sql" "fmt" "os" - "bufio" - "strconv" - "database/sql" "runtime/debug" - + "strconv" + "../query_gen/lib" ) const saltLength int = 32 + var db *sql.DB var scanner *bufio.Scanner -var db_adapter string = "mysql" -var db_host string -var db_username string -var db_password string -var db_name string -var db_port string -var site_name, site_url, server_port string +var dbAdapter = "mysql" +var dbHost string +var dbUsername string +var dbPassword string +var dbName string +var dbPort string +var siteName, siteURL, serverPort string -var default_adapter string = "mysql" -var default_host string = "localhost" -var default_username string = "root" -var default_dbname string = "gosora" -var default_site_name string = "Site Name" -var default_site_url string = "localhost" -var default_server_port string = "80" // 8080's a good one, if you're testing and don't want it to clash with port 80 +var defaultAdapter = "mysql" +var defaultHost = "localhost" +var defaultUsername = "root" +var defaultDbname = "gosora" +var defaultSiteName = "Site Name" +var defaultsiteURL = "localhost" +var defaultServerPort = "80" // 8080's a good one, if you're testing and don't want it to clash with port 80 -var init_database func()error = _init_mysql -var table_defs func()error = _table_defs_mysql -var initial_data func()error = _initial_data_mysql +// func() error, removing type to satisfy lint +var initDatabase = _initMysql +var tableDefs = _tableDefsMysql +var initialData = _initialDataMysql func main() { // Capture panics rather than immediately closing the window on Windows @@ -43,15 +50,15 @@ func main() { if r != nil { fmt.Println(r) debug.PrintStack() - press_any_key() + pressAnyKey() return } }() - + scanner = bufio.NewScanner(os.Stdin) fmt.Println("Welcome to Gosora's Installer") fmt.Println("We're going to take you through a few steps to help you get started :)") - if !get_database_details() { + if !getDatabaseDetails() { err := scanner.Err() if err != nil { fmt.Println(err) @@ -59,11 +66,11 @@ func main() { fmt.Println("Something went wrong!") } fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } - if !get_site_details() { + if !getSiteDetails() { err := scanner.Err() if err != nil { fmt.Println(err) @@ -71,78 +78,78 @@ func main() { fmt.Println("Something went wrong!") } fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } - - err := init_database() + + err := initDatabase() if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } - - err = table_defs() + + err = tableDefs() if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } - - hashed_password, salt, err := BcryptGeneratePassword("password") + + hashedPassword, salt, err := BcryptGeneratePassword("password") if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } - + // Build the admin user query - admin_user_stmt, err := qgen.Builder.SimpleInsert("users","name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, message, last_ip","'Admin',?,?,'admin@localhost',1,1,1,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','127.0.0.1'") + adminUserStmt, err := qgen.Builder.SimpleInsert("users", "name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, message, last_ip", "'Admin',?,?,'admin@localhost',1,1,1,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','127.0.0.1'") if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } - + // Run the admin user query - _, err = admin_user_stmt.Exec(hashed_password,salt) + _, err = adminUserStmt.Exec(hashedPassword, salt) if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } - - err = initial_data() + + err = initialData() if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } - - if db_adapter == "mysql" { - err = _mysql_seed_database() + + if dbAdapter == "mysql" { + err = _mysqlSeedDatabase() if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } } - + configContents := []byte(`package main func init() { // Site Info -site.Name = "` + site_name + `" // Should be a setting in the database +site.Name = "` + siteName + `" // Should be a setting in the database site.Email = "" // Should be a setting in the database -site.Url = "` + site_url + `" -site.Port = "` + server_port + `" +site.Url = "` + siteURL + `" +site.Port = "` + serverPort + `" site.EnableSsl = false site.EnableEmails = false site.HasProxy = false // Cloudflare counts as this, if it's sitting in the middle @@ -150,11 +157,11 @@ config.SslPrivkey = "" config.SslFullchain = "" // Database details -db_config.Host = "` + db_host + `" -db_config.Username = "` + db_username + `" -db_config.Password = "` + db_password + `" -db_config.Dbname = "` + db_name + `" -db_config.Port = "` + db_port + `" // You probably won't need to change this +db_config.Host = "` + dbHost + `" +db_config.Username = "` + dbUsername + `" +db_config.Password = "` + dbPassword + `" +db_config.Dbname = "` + dbName + `" +db_config.Port = "` + dbPort + `" // You probably won't need to change this // Limiters config.MaxRequestSize = 5 * megabyte @@ -195,7 +202,7 @@ dev.DebugMode = true if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } @@ -204,7 +211,7 @@ dev.DebugMode = true if err != nil { fmt.Println(err) fmt.Println("Aborting installation...") - press_any_key() + pressAnyKey() return } @@ -214,121 +221,122 @@ dev.DebugMode = true fmt.Println("Yay, you have successfully installed Gosora!") fmt.Println("Your name is Admin and you can login with the password 'password'. Don't forget to change it! Seriously. It's really insecure.") - press_any_key() + pressAnyKey() } -func get_database_details() bool { +func getDatabaseDetails() bool { fmt.Println("Which database driver do you wish to use? mysql, mysql, or mysql? Default: mysql") if !scanner.Scan() { return false } - db_adapter = scanner.Text() - if db_adapter == "" { - db_adapter = default_adapter + dbAdapter = scanner.Text() + if dbAdapter == "" { + dbAdapter = defaultAdapter } - db_adapter = set_db_adapter(db_adapter) - fmt.Println("Set database adapter to " + db_adapter) - - fmt.Println("Database Host? Default: " + default_host) - if !scanner.Scan() { - return false - } - db_host = scanner.Text() - if db_host == "" { - db_host = default_host - } - fmt.Println("Set database host to " + db_host) + dbAdapter = setDBAdapter(dbAdapter) + fmt.Println("Set database adapter to " + dbAdapter) - fmt.Println("Database Username? Default: " + default_username) + fmt.Println("Database Host? Default: " + defaultHost) if !scanner.Scan() { return false } - db_username = scanner.Text() - if db_username == "" { - db_username = default_username + dbHost = scanner.Text() + if dbHost == "" { + dbHost = defaultHost } - fmt.Println("Set database username to " + db_username) + fmt.Println("Set database host to " + dbHost) + + fmt.Println("Database Username? Default: " + defaultUsername) + if !scanner.Scan() { + return false + } + dbUsername = scanner.Text() + if dbUsername == "" { + dbUsername = defaultUsername + } + fmt.Println("Set database username to " + dbUsername) fmt.Println("Database Password? Default: ''") if !scanner.Scan() { return false } - db_password = scanner.Text() - if len(db_password) == 0 { - fmt.Println("You didn't set a password for this user. This won't block the installation process, but it might create security issues in the future.\n") + dbPassword = scanner.Text() + if len(dbPassword) == 0 { + fmt.Println("You didn't set a password for this user. This won't block the installation process, but it might create security issues in the future.") + fmt.Println("") } else { - fmt.Println("Set password to " + obfuscate_password(db_password)) + fmt.Println("Set password to " + obfuscatePassword(dbPassword)) } - fmt.Println("Database Name? Pick a name you like or one provided to you. Default: " + default_dbname) + fmt.Println("Database Name? Pick a name you like or one provided to you. Default: " + defaultDbname) if !scanner.Scan() { return false } - db_name = scanner.Text() - if db_name == "" { - db_name = default_dbname + dbName = scanner.Text() + if dbName == "" { + dbName = defaultDbname } - fmt.Println("Set database name to " + db_name) + fmt.Println("Set database name to " + dbName) return true } -func get_site_details() bool { +func getSiteDetails() bool { fmt.Println("Okay. We also need to know some actual information about your site!") - fmt.Println("What's your site's name? Default: " + default_site_name) + fmt.Println("What's your site's name? Default: " + defaultSiteName) if !scanner.Scan() { return false } - site_name = scanner.Text() - if site_name == "" { - site_name = default_site_name + siteName = scanner.Text() + if siteName == "" { + siteName = defaultSiteName } - fmt.Println("Set the site name to " + site_name) + fmt.Println("Set the site name to " + siteName) - fmt.Println("What's your site's url? Default: " + default_site_url) + fmt.Println("What's your site's url? Default: " + defaultsiteURL) if !scanner.Scan() { return false } - site_url = scanner.Text() - if site_url == "" { - site_url = default_site_url + siteURL = scanner.Text() + if siteURL == "" { + siteURL = defaultsiteURL } - fmt.Println("Set the site url to " + site_url) + fmt.Println("Set the site url to " + siteURL) - fmt.Println("What port do you want the server to listen on? If you don't know what this means, you should probably leave it on the default. Default: " + default_server_port) + fmt.Println("What port do you want the server to listen on? If you don't know what this means, you should probably leave it on the default. Default: " + defaultServerPort) if !scanner.Scan() { return false } - server_port = scanner.Text() - if server_port == "" { - server_port = default_server_port + serverPort = scanner.Text() + if serverPort == "" { + serverPort = defaultServerPort } - _, err := strconv.Atoi(server_port) + _, err := strconv.Atoi(serverPort) if err != nil { fmt.Println("That's not a valid number!") return false } - fmt.Println("Set the server port to " + server_port) + fmt.Println("Set the server port to " + serverPort) return true } -func set_db_adapter(name string) string { - switch(name) { - //case "wip-pgsql": - // set_pgsql_adapter() - // return "wip-pgsql" +func setDBAdapter(name string) string { + switch name { + //case "wip-pgsql": + // set_pgsql_adapter() + // return "wip-pgsql" } - _set_mysql_adapter() + _setMysqlAdapter() return "mysql" } -func obfuscate_password(password string) (out string) { +func obfuscatePassword(password string) (out string) { for i := 0; i < len(password); i++ { out += "*" } return out } -func press_any_key() { +func pressAnyKey() { //fmt.Println("Press any key to exit...") fmt.Println("Please press enter to exit...") for scanner.Scan() { diff --git a/install/mysql.go b/install/mysql.go index c4a3f25e..6644c994 100644 --- a/install/mysql.go +++ b/install/mysql.go @@ -1,34 +1,39 @@ -/* Copyright Azareal 2017 - 2018 */ +/* +* +* Gosora MySQL Interface +* Copyright Azareal 2017 - 2018 +* + */ package main import ( - "fmt" "bytes" - "strings" - "strconv" + "database/sql" + "fmt" "io/ioutil" "path/filepath" - "database/sql" + "strconv" + "strings" "../query_gen/lib" _ "github.com/go-sql-driver/mysql" ) -//var db_collation string = "utf8mb4_general_ci" +//var dbCollation string = "utf8mb4_general_ci" -func _set_mysql_adapter() { - db_port = "3306" - init_database = _init_mysql - table_defs = _table_defs_mysql - initial_data = _initial_data_mysql +func _setMysqlAdapter() { + dbPort = "3306" + initDatabase = _initMysql + tableDefs = _tableDefsMysql + initialData = _initialDataMysql } -func _init_mysql() (err error) { - _db_password := db_password - if _db_password != "" { - _db_password = ":" + _db_password +func _initMysql() (err error) { + _dbPassword := dbPassword + if _dbPassword != "" { + _dbPassword = ":" + _dbPassword } - db, err = sql.Open("mysql",db_username + _db_password + "@tcp(" + db_host + ":" + db_port + ")/") + db, err = sql.Open("mysql", dbUsername+_dbPassword+"@tcp("+dbHost+":"+dbPort+")/") if err != nil { return err } @@ -41,22 +46,22 @@ func _init_mysql() (err error) { fmt.Println("Successfully connected to the database") var waste string - err = db.QueryRow("SHOW DATABASES LIKE '" + db_name + "'").Scan(&waste) + err = db.QueryRow("SHOW DATABASES LIKE '" + dbName + "'").Scan(&waste) if err != nil && err != sql.ErrNoRows { return err } if err == sql.ErrNoRows { fmt.Println("Unable to find the database. Attempting to create it") - _,err = db.Exec("CREATE DATABASE IF NOT EXISTS " + db_name + "") + _, err = db.Exec("CREATE DATABASE IF NOT EXISTS " + dbName + "") if err != nil { return err } fmt.Println("The database was successfully created") } - fmt.Println("Switching to database " + db_name) - _, err = db.Exec("USE " + db_name) + fmt.Println("Switching to database " + dbName) + _, err = db.Exec("USE " + dbName) if err != nil { return err } @@ -71,22 +76,22 @@ func _init_mysql() (err error) { return nil } -func _table_defs_mysql() error { +func _tableDefsMysql() error { //fmt.Println("Creating the tables") files, _ := ioutil.ReadDir("./schema/mysql/") for _, f := range files { - if !strings.HasPrefix(f.Name(),"query_") { + if !strings.HasPrefix(f.Name(), "query_") { continue } var table string var ext string - table = strings.TrimPrefix(f.Name(),"query_") + table = strings.TrimPrefix(f.Name(), "query_") ext = filepath.Ext(table) if ext != ".sql" { continue } - table = strings.TrimSuffix(table,ext) + table = strings.TrimSuffix(table, ext) fmt.Println("Creating table '" + table + "'") data, err := ioutil.ReadFile("./schema/mysql/" + f.Name()) @@ -97,7 +102,7 @@ func _table_defs_mysql() error { _, err = db.Exec(string(data)) if err != nil { - fmt.Println("Failed query:",string(data)) + fmt.Println("Failed query:", string(data)) return err } } @@ -105,10 +110,10 @@ func _table_defs_mysql() error { return nil } -func _initial_data_mysql() error { +func _initialDataMysql() error { return nil // Coming Soon - fmt.Println("Seeding the tables") + /*fmt.Println("Seeding the tables") data, err := ioutil.ReadFile("./schema/mysql/inserts.sql") if err != nil { return err @@ -122,10 +127,10 @@ func _initial_data_mysql() error { } //fmt.Println("Finished inserting the database data") - return nil + return nil*/ } -func _mysql_seed_database() error { +func _mysqlSeedDatabase() error { fmt.Println("Opening the database seed file") sqlContents, err := ioutil.ReadFile("./mysql.sql") if err != nil { diff --git a/install/pgsql.go b/install/pgsql.go index 2233a00b..b22b322c 100644 --- a/install/pgsql.go +++ b/install/pgsql.go @@ -1,5 +1,10 @@ -/* Under heavy development */ -/* Copyright Azareal 2017 - 2018 */ +/* +* +* Gosora PostgreSQL Interface +* Under heavy development +* Copyright Azareal 2017 - 2018 +* + */ package main import "fmt" @@ -8,30 +13,30 @@ import "database/sql" import _ "github.com/go-sql-driver/mysql" // We don't need SSL to run an installer... Do we? -var db_sslmode = "disable" +var dbSslmode = "disable" -func _set_pgsql_adapter() { - db_port = "5432" - init_database = _init_pgsql +func _setPgsqlAdapter() { + dbPort = "5432" + initDatabase = _initPgsql } -func _init_pgsql() (err error) { - _db_password := db_password - if _db_password != "" { - _db_password = " password=" + _pg_escape_bit(_db_password) +func _initPgsql() (err error) { + _dbPassword := dbPassword + if _dbPassword != "" { + _dbPassword = " password=" + _pgEscapeBit(_dbPassword) } - db, err = sql.Open("postgres", "host='" + _pg_escape_bit(db_host) + "' port='" + _pg_escape_bit(db_port) + "' user='" + _pg_escape_bit(db_username) + "' dbname='" + _pg_escape_bit(db_name) + "'" + _db_password + " sslmode='" + db_sslmode + "'") + db, err = sql.Open("postgres", "host='"+_pgEscapeBit(dbHost)+"' port='"+_pgEscapeBit(dbPort)+"' user='"+_pgEscapeBit(dbUsername)+"' dbname='"+_pgEscapeBit(dbName)+"'"+_dbPassword+" sslmode='"+dbSslmode+"'") if err != nil { return err } fmt.Println("Successfully connected to the database") - + // TO-DO: Create the database, if it doesn't exist - + return nil } -func _pg_escape_bit(bit string) string { +func _pgEscapeBit(bit string) string { // TO-DO: Write a custom parser, so that backslashes work properly in the sql.Open string. Do something similar for the database driver, if possible? - return strings.Replace(bit,"'","\\'",-1) -} \ No newline at end of file + return strings.Replace(bit, "'", "\\'", -1) +} diff --git a/install/utils.go b/install/utils.go index d07988a6..770bb338 100644 --- a/install/utils.go +++ b/install/utils.go @@ -6,7 +6,7 @@ import "golang.org/x/crypto/bcrypt" // Generate a cryptographically secure set of random bytes.. func GenerateSafeString(length int) (string, error) { - rb := make([]byte,length) + rb := make([]byte, length) _, err := rand.Read(rb) if err != nil { return "", err @@ -14,24 +14,25 @@ func GenerateSafeString(length int) (string, error) { return base64.URLEncoding.EncodeToString(rb), nil } -func BcryptGeneratePassword(password string) (hashed_password string, salt string, err error) { +// Generate a bcrypt hash from a password and a salt +func BcryptGeneratePassword(password string) (hashedPassword string, salt string, err error) { salt, err = GenerateSafeString(saltLength) if err != nil { return "", "", err } password = password + salt - hashed_password, err = BcryptGeneratePasswordNoSalt(password) + hashedPassword, err = bcryptGeneratePasswordNoSalt(password) if err != nil { return "", "", err } - return hashed_password, salt, nil + return hashedPassword, salt, nil } -func BcryptGeneratePasswordNoSalt(password string) (hash string, err error) { - hashed_password, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) +func bcryptGeneratePasswordNoSalt(password string) (hash string, err error) { + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) if err != nil { return "", err } - return string(hashed_password), nil + return string(hashedPassword), nil } diff --git a/main.go b/main.go index addc4e63..eeb0493f 100644 --- a/main.go +++ b/main.go @@ -3,17 +3,17 @@ package main import ( "fmt" - "log" - "strings" - "time" "io" - "os" - "sync/atomic" + "log" "net/http" + "os" + "strings" + "sync/atomic" + "time" //"runtime/pprof" ) -var version Version = Version{Major:0,Minor:1,Patch:0,Tag:"dev"} +var version = Version{Major: 0, Minor: 1, Patch: 0, Tag: "dev"} const hour int = 60 * 60 const day int = hour * 24 @@ -26,38 +26,40 @@ const gigabyte int = megabyte * 1024 const terabyte int = gigabyte * 1024 const saltLength int = 32 const sessionLength int = 80 -var enable_websockets bool = false // Don't change this, the value is overwritten by an initialiser + +var enableWebsockets = false // Don't change this, the value is overwritten by an initialiser var router *GenRouter var startTime time.Time -var external_sites map[string]string = map[string]string{ - "YT":"https://www.youtube.com/", +var externalSites = map[string]string{ + "YT": "https://www.youtube.com/", } var groups []Group var groupCapCount int -var static_files map[string]SFile = make(map[string]SFile) -var logWriter io.Writer = io.MultiWriter(os.Stderr) +var staticFiles = make(map[string]SFile) +var logWriter = io.MultiWriter(os.Stderr) type WordFilter struct { - ID int - Find string + ID int + Find string Replacement string } type WordFilterBox map[int]WordFilter + var wordFilterBox atomic.Value // An atomic value holding a WordFilterBox func init() { wordFilterBox.Store(WordFilterBox(make(map[int]WordFilter))) } -func init_word_filters() error { +func initWordFilters() error { rows, err := get_word_filters_stmt.Query() if err != nil { return err } defer rows.Close() - var wordFilters WordFilterBox = wordFilterBox.Load().(WordFilterBox) + var wordFilters = wordFilterBox.Load().(WordFilterBox) var wfid int var find string var replacement string @@ -67,36 +69,36 @@ func init_word_filters() error { if err != nil { return err } - wordFilters[wfid] = WordFilter{ID:wfid,Find:find,Replacement:replacement} + wordFilters[wfid] = WordFilter{ID: wfid, Find: find, Replacement: replacement} } wordFilterBox.Store(wordFilters) return rows.Err() } -func add_word_filter(id int, find string, replacement string) { +func addWordFilter(id int, find string, replacement string) { wordFilters := wordFilterBox.Load().(WordFilterBox) - wordFilters[id] = WordFilter{ID:id,Find:find,Replacement:replacement} + wordFilters[id] = WordFilter{ID: id, Find: find, Replacement: replacement} wordFilterBox.Store(wordFilters) } -func process_config() { - config.Noavatar = strings.Replace(config.Noavatar,"{site_url}",site.Url,-1) +func processConfig() { + config.Noavatar = strings.Replace(config.Noavatar, "{site_url}", site.Url, -1) if site.Port != "80" && site.Port != "443" { - site.Url = strings.TrimSuffix(site.Url,"/") - site.Url = strings.TrimSuffix(site.Url,"\\") - site.Url = strings.TrimSuffix(site.Url,":") + site.Url = strings.TrimSuffix(site.Url, "/") + site.Url = strings.TrimSuffix(site.Url, "\\") + site.Url = strings.TrimSuffix(site.Url, ":") site.Url = site.Url + ":" + site.Port } } -func main(){ +func main() { // TO-DO: Have a file for each run with the time/date the server started as the file name? // TO-DO: Log panics with recover() - f, err := os.OpenFile("./operations.log",os.O_WRONLY|os.O_APPEND|os.O_CREATE,0755) + f, err := os.OpenFile("./operations.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755) if err != nil { log.Fatal(err) } - logWriter = io.MultiWriter(os.Stderr,f) + logWriter = io.MultiWriter(os.Stderr, f) log.SetOutput(logWriter) //if profiling { @@ -113,16 +115,20 @@ func main(){ //timeLocation = startTime.Location() log.Print("Processing configuration data") - process_config() + processConfig() - init_themes() - err = init_database() + err = initThemes() if err != nil { log.Fatal(err) } - init_templates() - err = init_errors() + err = initDatabase() + if err != nil { + log.Fatal(err) + } + + initTemplates() + err = initErrors() if err != nil { log.Fatal(err) } @@ -135,10 +141,14 @@ func main(){ topics = NewSqlTopicStore() } - init_static_files() + log.Print("Loading the static files.") + err = initStaticFiles() + if err != nil { + log.Fatal(err) + } log.Print("Initialising the widgets") - err = init_widgets() + err = initWidgets() if err != nil { log.Fatal(err) } @@ -146,34 +156,34 @@ func main(){ log.Print("Initialising the authentication system") auth = NewDefaultAuth() - err = init_word_filters() + err = initWordFilters() if err != nil { log.Fatal(err) } // Run this goroutine once a second - second_ticker := time.NewTicker(1 * time.Second) - fifteen_minute_ticker := time.NewTicker(15 * time.Minute) + secondTicker := time.NewTicker(1 * time.Second) + fifteenMinuteTicker := time.NewTicker(15 * time.Minute) //hour_ticker := time.NewTicker(1 * time.Hour) go func() { for { select { - case <- second_ticker.C: - //log.Print("Running the second ticker") - err := handle_expired_scheduled_groups() - if err != nil { - LogError(err) - } - // TO-DO: Handle delayed moderation tasks - // TO-DO: Handle the daily clean-up. Move this to a 24 hour task? - // TO-DO: Sync with the database, if there are any changes - // TO-DO: Manage the TopicStore, UserStore, and ForumStore - // TO-DO: Alert the admin, if CPU usage, RAM usage, or the number of posts in the past second are too high - // TO-DO: Clean-up alerts with no unread matches which are over two weeks old. Move this to a 24 hour task? - case <- fifteen_minute_ticker.C: - // TO-DO: Automatically lock topics, if they're really old, and the associated setting is enabled. - // TO-DO: Publish scheduled posts. - // TO-DO: Delete the empty users_groups_scheduler entries + case <-secondTicker.C: + //log.Print("Running the second ticker") + err := handleExpiredScheduledGroups() + if err != nil { + LogError(err) + } + // TO-DO: Handle delayed moderation tasks + // TO-DO: Handle the daily clean-up. Move this to a 24 hour task? + // TO-DO: Sync with the database, if there are any changes + // TO-DO: Manage the TopicStore, UserStore, and ForumStore + // TO-DO: Alert the admin, if CPU usage, RAM usage, or the number of posts in the past second are too high + // TO-DO: Clean-up alerts with no unread matches which are over two weeks old. Move this to a 24 hour task? + case <-fifteenMinuteTicker.C: + // TO-DO: Automatically lock topics, if they're really old, and the associated setting is enabled. + // TO-DO: Publish scheduled posts. + // TO-DO: Delete the empty users_groups_scheduler entries } } }() @@ -231,6 +241,7 @@ func main(){ router.HandleFunc("/users/ban/submit/", route_ban_submit) router.HandleFunc("/users/unban/", route_unban) router.HandleFunc("/users/activate/", route_activate) + router.HandleFunc("/users/ips/", route_ips) // The Control Panel ///router.HandleFunc("/panel/", route_panel) @@ -267,7 +278,7 @@ func main(){ router.HandleFunc("/ws/", route_websockets) log.Print("Initialising the plugins") - init_plugins() + initPlugins() defer db.Close() @@ -281,7 +292,7 @@ func main(){ if site.Port == "" { site.Port = "80" } - err = http.ListenAndServe(":" + site.Port, router) + err = http.ListenAndServe(":"+site.Port, router) } else { if site.Port == "" { site.Port = "443" @@ -296,7 +307,7 @@ func main(){ } }() } - err = http.ListenAndServeTLS(":" + site.Port, config.SslFullchain, config.SslPrivkey, router) + err = http.ListenAndServeTLS(":"+site.Port, config.SslFullchain, config.SslPrivkey, router) } // Why did the server stop? diff --git a/misc_test.go b/misc_test.go index af13ba8a..1b9c40dc 100644 --- a/misc_test.go +++ b/misc_test.go @@ -5,210 +5,213 @@ import "testing" // TO-DO: Generate a test database to work with rather than a live one func TestUserStore(t *testing.T) { - if !gloinited { - gloinit() + if !gloinited { + err := gloinit() + if err != nil { + t.Fatal(err) + } } - if !plugins_inited { - init_plugins() + if !pluginsInited { + initPlugins() } - var user *User - var err error + var user *User + var err error - user, err = users.CascadeGet(-1) - if err == nil { - t.Error("UID #-1 shouldn't exist") - } else if err != ErrNoRows { - t.Fatal(err) - } + user, err = users.CascadeGet(-1) + if err == nil { + t.Error("UID #-1 shouldn't exist") + } else if err != ErrNoRows { + t.Fatal(err) + } - user, err = users.CascadeGet(0) - if err == nil { - t.Error("UID #0 shouldn't exist") - } else if err != ErrNoRows { - t.Fatal(err) - } + user, err = users.CascadeGet(0) + if err == nil { + t.Error("UID #0 shouldn't exist") + } else if err != ErrNoRows { + t.Fatal(err) + } - user, err = users.CascadeGet(1) - if err == ErrNoRows { - t.Error("Couldn't find UID #1") - } else if err != nil { - t.Fatal(err) - } + user, err = users.CascadeGet(1) + if err == ErrNoRows { + t.Error("Couldn't find UID #1") + } else if err != nil { + t.Fatal(err) + } - if user.ID != 1 { - t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.") - } + if user.ID != 1 { + t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.") + } - // TO-DO: Lock onto the specific error type. Is this even possible without sacrificing the detailed information in the error message? - var userList map[int]*User - userList, err = users.BulkCascadeGetMap([]int{-1}) - if err == nil { - t.Error("UID #-1 shouldn't exist") - } + // TO-DO: Lock onto the specific error type. Is this even possible without sacrificing the detailed information in the error message? + var userList map[int]*User + _, err = users.BulkCascadeGetMap([]int{-1}) + if err == nil { + t.Error("UID #-1 shouldn't exist") + } - userList, err = users.BulkCascadeGetMap([]int{0}) - if err == nil { - t.Error("UID #0 shouldn't exist") - } + _, err = users.BulkCascadeGetMap([]int{0}) + if err == nil { + t.Error("UID #0 shouldn't exist") + } - userList, err = users.BulkCascadeGetMap([]int{1}) - if err == ErrNoRows { - t.Error("Couldn't find UID #1") - } else if err != nil { - t.Fatal(err) - } + userList, err = users.BulkCascadeGetMap([]int{1}) + if err == ErrNoRows { + t.Error("Couldn't find UID #1") + } else if err != nil { + t.Fatal(err) + } - if len(userList) == 0 { - t.Error("The returned map is empty for UID #0") - } else if len(userList) > 1 { - t.Error("Too many results were returned for UID #0") - } + if len(userList) == 0 { + t.Error("The returned map is empty for UID #0") + } else if len(userList) > 1 { + t.Error("Too many results were returned for UID #0") + } - user, ok := userList[1] - if !ok { - t.Error("We couldn't find UID #0 in the returned map") - t.Error("userList",userList) - } + user, ok := userList[1] + if !ok { + t.Error("We couldn't find UID #0 in the returned map") + t.Error("userList", userList) + } - if user.ID != 1 { - t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.") - } + if user.ID != 1 { + t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.") + } } func TestForumStore(t *testing.T) { - if !gloinited { + if !gloinited { gloinit() } - if !plugins_inited { - init_plugins() + if !pluginsInited { + initPlugins() } - var forum *Forum - var err error + var forum *Forum + var err error - forum, err = fstore.CascadeGet(-1) - if err == nil { - t.Error("FID #-1 shouldn't exist") - } else if err != ErrNoRows { - t.Fatal(err) - } + forum, err = fstore.CascadeGet(-1) + if err == nil { + t.Error("FID #-1 shouldn't exist") + } else if err != ErrNoRows { + t.Fatal(err) + } - forum, err = fstore.CascadeGet(0) - if err == ErrNoRows { - t.Error("Couldn't find FID #0") - } else if err != nil { - t.Fatal(err) - } + forum, err = fstore.CascadeGet(0) + if err == ErrNoRows { + t.Error("Couldn't find FID #0") + } else if err != nil { + t.Fatal(err) + } - if forum.ID != 0 { - t.Error("forum.ID doesn't not match the requested UID. Got '" + strconv.Itoa(forum.ID) + "' instead.") - } - if forum.Name != "Uncategorised" { - t.Error("FID #0 is named '" + forum.Name + "' and not 'Uncategorised'") - } + if forum.ID != 0 { + t.Error("forum.ID doesn't not match the requested UID. Got '" + strconv.Itoa(forum.ID) + "' instead.") + } + if forum.Name != "Uncategorised" { + t.Error("FID #0 is named '" + forum.Name + "' and not 'Uncategorised'") + } - forum, err = fstore.CascadeGet(1) - if err == ErrNoRows { - t.Error("Couldn't find FID #1") - } else if err != nil { - t.Fatal(err) - } + forum, err = fstore.CascadeGet(1) + if err == ErrNoRows { + t.Error("Couldn't find FID #1") + } else if err != nil { + t.Fatal(err) + } - if forum.ID != 1 { - t.Error("forum.ID doesn't not match the requested UID. Got '" + strconv.Itoa(forum.ID) + "' instead.'") - } - if forum.Name != "Reports" { - t.Error("FID #0 is named '" + forum.Name + "' and not 'Reports'") - } + if forum.ID != 1 { + t.Error("forum.ID doesn't not match the requested UID. Got '" + strconv.Itoa(forum.ID) + "' instead.'") + } + if forum.Name != "Reports" { + t.Error("FID #0 is named '" + forum.Name + "' and not 'Reports'") + } - forum, err = fstore.CascadeGet(2) - if err == ErrNoRows { - t.Error("Couldn't find FID #2") - } else if err != nil { - t.Fatal(err) - } + forum, err = fstore.CascadeGet(2) + if err == ErrNoRows { + t.Error("Couldn't find FID #2") + } else if err != nil { + t.Fatal(err) + } } func TestSlugs(t *testing.T) { - var res string - var msgList []ME_Pair + var res string + var msgList []ME_Pair - msgList = addMEPair(msgList,"Unknown","unknown") - msgList = addMEPair(msgList,"Unknown2","unknown2") - msgList = addMEPair(msgList,"Unknown ","unknown") - msgList = addMEPair(msgList,"Unknown 2","unknown-2") - msgList = addMEPair(msgList,"Unknown 2","unknown-2") - msgList = addMEPair(msgList,"Admin Alice","admin-alice") - msgList = addMEPair(msgList,"Admin_Alice","adminalice") - msgList = addMEPair(msgList,"Admin_Alice-","adminalice") - msgList = addMEPair(msgList,"-Admin_Alice-","adminalice") - msgList = addMEPair(msgList,"-Admin@Alice-","adminalice") - msgList = addMEPair(msgList,"-Admin😀Alice-","adminalice") - msgList = addMEPair(msgList,"u","u") - msgList = addMEPair(msgList,"","untitled") - msgList = addMEPair(msgList," ","untitled") - msgList = addMEPair(msgList,"-","untitled") - msgList = addMEPair(msgList,"--","untitled") - msgList = addMEPair(msgList,"é","é") - msgList = addMEPair(msgList,"-é-","é") + msgList = addMEPair(msgList, "Unknown", "unknown") + msgList = addMEPair(msgList, "Unknown2", "unknown2") + msgList = addMEPair(msgList, "Unknown ", "unknown") + msgList = addMEPair(msgList, "Unknown 2", "unknown-2") + msgList = addMEPair(msgList, "Unknown 2", "unknown-2") + msgList = addMEPair(msgList, "Admin Alice", "admin-alice") + msgList = addMEPair(msgList, "Admin_Alice", "adminalice") + msgList = addMEPair(msgList, "Admin_Alice-", "adminalice") + msgList = addMEPair(msgList, "-Admin_Alice-", "adminalice") + msgList = addMEPair(msgList, "-Admin@Alice-", "adminalice") + msgList = addMEPair(msgList, "-Admin😀Alice-", "adminalice") + msgList = addMEPair(msgList, "u", "u") + msgList = addMEPair(msgList, "", "untitled") + msgList = addMEPair(msgList, " ", "untitled") + msgList = addMEPair(msgList, "-", "untitled") + msgList = addMEPair(msgList, "--", "untitled") + msgList = addMEPair(msgList, "é", "é") + msgList = addMEPair(msgList, "-é-", "é") - for _, item := range msgList { - t.Log("Testing string '"+item.Msg+"'") - res = name_to_slug(item.Msg) - if res != item.Expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",item.Expects) - } - } + for _, item := range msgList { + t.Log("Testing string '" + item.Msg + "'") + res = nameToSlug(item.Msg) + if res != item.Expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", item.Expects) + } + } } func TestAuth(t *testing.T) { - // bcrypt likes doing stupid things, so this test will probably fail - var real_password string - var hashed_password string - var password string - var salt string - var err error + // bcrypt likes doing stupid things, so this test will probably fail + var realPassword string + var hashedPassword string + var password string + var salt string + var err error - /* No extra salt tests, we might not need this extra salt, as bcrypt has it's own? */ - real_password = "Madame Cassandra's Mystic Orb" - t.Log("Set real_password to '" + real_password + "'") - t.Log("Hashing the real password") - hashed_password, err = BcryptGeneratePasswordNoSalt(real_password) - if err != nil { - t.Error(err) - } + /* No extra salt tests, we might not need this extra salt, as bcrypt has it's own? */ + realPassword = "Madame Cassandra's Mystic Orb" + t.Log("Set real_password to '" + realPassword + "'") + t.Log("Hashing the real password") + hashedPassword, err = BcryptGeneratePasswordNoSalt(realPassword) + if err != nil { + t.Error(err) + } - password = real_password - t.Log("Testing password '" + password + "'") - t.Log("Testing salt '" + salt + "'") - err = CheckPassword(hashed_password,password,salt) - if err == ErrMismatchedHashAndPassword { - t.Error("The two don't match") - } else if err == ErrPasswordTooLong { - t.Error("CheckPassword thinks the password is too long") - } else if err != nil { - t.Error(err) - } + password = realPassword + t.Log("Testing password '" + password + "'") + t.Log("Testing salt '" + salt + "'") + err = CheckPassword(hashedPassword, password, salt) + if err == ErrMismatchedHashAndPassword { + t.Error("The two don't match") + } else if err == ErrPasswordTooLong { + t.Error("CheckPassword thinks the password is too long") + } else if err != nil { + t.Error(err) + } - password = "hahaha" - t.Log("Testing password '" + password + "'") - t.Log("Testing salt '" + salt + "'") - err = CheckPassword(hashed_password,password,salt) - if err == ErrPasswordTooLong { - t.Error("CheckPassword thinks the password is too long") - } else if err == nil { - t.Error("The two shouldn't match!") - } + password = "hahaha" + t.Log("Testing password '" + password + "'") + t.Log("Testing salt '" + salt + "'") + err = CheckPassword(hashedPassword, password, salt) + if err == ErrPasswordTooLong { + t.Error("CheckPassword thinks the password is too long") + } else if err == nil { + t.Error("The two shouldn't match!") + } - password = "Madame Cassandra's Mystic" - t.Log("Testing password '" + password + "'") - t.Log("Testing salt '" + salt + "'") - err = CheckPassword(hashed_password,password,salt) - if err == ErrPasswordTooLong { - t.Error("CheckPassword thinks the password is too long") - } else if err == nil { - t.Error("The two shouldn't match!") - } + password = "Madame Cassandra's Mystic" + t.Log("Testing password '" + password + "'") + t.Log("Testing salt '" + salt + "'") + err = CheckPassword(hashedPassword, password, salt) + if err == ErrPasswordTooLong { + t.Error("CheckPassword thinks the password is too long") + } else if err == nil { + t.Error("The two shouldn't match!") + } } diff --git a/mod_routes.go b/mod_routes.go index 0df52f37..472b840e 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -3,152 +3,151 @@ package main import ( //"log" //"fmt" - "strconv" - "time" + "html" "net" "net/http" - "html" + "strconv" + "time" ) func route_edit_topic(w http.ResponseWriter, r *http.Request, user User) { //log.Print("in route_edit_topic") err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } - is_js := r.PostFormValue("js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("js") == "1") var tid int tid, err = strconv.Atoi(r.URL.Path[len("/topic/edit/submit/"):]) if err != nil { - PreErrorJSQ("The provided TopicID is not a valid number.",w,r,is_js) + PreErrorJSQ("The provided TopicID is not a valid number.", w, r, isJs) return } - old_topic, err := topics.CascadeGet(tid) + oldTopic, err := topics.CascadeGet(tid) if err == ErrNoRows { - PreErrorJSQ("The topic you tried to edit doesn't exist.",w,r,is_js) + PreErrorJSQ("The topic you tried to edit doesn't exist.", w, r, isJs) return } else if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - ok := SimpleForumSessionCheck(w,r,&user,old_topic.ParentID) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, oldTopic.ParentID) if !ok { return } if !user.Perms.ViewTopic || !user.Perms.EditTopic { - NoPermissionsJSQ(w,r,user,is_js) + NoPermissionsJSQ(w, r, user, isJs) return } - topic_name := r.PostFormValue("topic_name") - topic_status := r.PostFormValue("topic_status") - is_closed := (topic_status == "closed") + topicName := r.PostFormValue("topic_name") + topicStatus := r.PostFormValue("topic_status") + isClosed := (topicStatus == "closed") - topic_content := html.EscapeString(r.PostFormValue("topic_content")) - _, err = edit_topic_stmt.Exec(topic_name, preparse_message(topic_content), parse_message(html.EscapeString(preparse_message(topic_content))), is_closed, tid) + topicContent := html.EscapeString(r.PostFormValue("topic_content")) + _, err = edit_topic_stmt.Exec(topicName, preparseMessage(topicContent), parseMessage(html.EscapeString(preparseMessage(topicContent))), isClosed, tid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - if old_topic.Is_Closed != is_closed { + if oldTopic.IsClosed != isClosed { var action string - if is_closed { + if isClosed { action = "lock" } else { action = "unlock" } - err = addModLog(action,tid,"topic",ipaddress,user.ID) + err = addModLog(action, tid, "topic", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = create_action_reply_stmt.Exec(tid,action,ipaddress,user.ID) + _, err = create_action_reply_stmt.Exec(tid, action, ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } _, err = add_replies_to_topic_stmt.Exec(1, user.ID, tid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - err = fstore.UpdateLastTopic(topic_name,tid,user.Name,user.ID,time.Now().Format("2006-01-02 15:04:05"),old_topic.ParentID) + err = fstore.UpdateLastTopic(topicName, tid, user.Name, user.ID, time.Now().Format("2006-01-02 15:04:05"), oldTopic.ParentID) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } } err = topics.Load(tid) if err == ErrNoRows { - LocalErrorJSQ("This topic no longer exists!",w,r,user,is_js) + LocalErrorJSQ("This topic no longer exists!", w, r, user, isJs) return } else if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - if is_js == "0" { - http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) + if !isJs { + http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther) } else { - w.Write(success_json_bytes) + _, _ = w.Write(successJSONBytes) } } func route_delete_topic(w http.ResponseWriter, r *http.Request, user User) { tid, err := strconv.Atoi(r.URL.Path[len("/topic/delete/submit/"):]) if err != nil { - PreError("The provided TopicID is not a valid number.",w,r) + PreError("The provided TopicID is not a valid number.", w, r) return } topic, err := topics.CascadeGet(tid) if err == ErrNoRows { - PreError("The topic you tried to delete doesn't exist.",w,r) + PreError("The topic you tried to delete doesn't exist.", w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - ok := SimpleForumSessionCheck(w,r,&user,topic.ParentID) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, topic.ParentID) if !ok { return } if !user.Perms.ViewTopic || !user.Perms.DeleteTopic { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } _, err = delete_topic_stmt.Exec(tid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - err = addModLog("delete",tid,"topic",ipaddress,user.ID) + err = addModLog("delete", tid, "topic", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -160,18 +159,18 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request, user User) { }*/ //log.Print("Topic #" + strconv.Itoa(tid) + " was deleted by User #" + strconv.Itoa(user.ID)) - http.Redirect(w,r,"/",http.StatusSeeOther) + http.Redirect(w, r, "/", http.StatusSeeOther) - wcount := word_count(topic.Content) - err = decrease_post_user_stats(wcount,topic.CreatedBy,true,user) + wcount := wordCount(topic.Content) + err = decrease_post_user_stats(wcount, topic.CreatedBy, true, user) if err != nil { - InternalError(err,w) + InternalError(err, w) return } err = fstore.DecrementTopicCount(topic.ParentID) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } topics.Remove(tid) @@ -180,134 +179,133 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request, user User) { func route_stick_topic(w http.ResponseWriter, r *http.Request, user User) { tid, err := strconv.Atoi(r.URL.Path[len("/topic/stick/submit/"):]) if err != nil { - PreError("The provided TopicID is not a valid number.",w,r) + PreError("The provided TopicID is not a valid number.", w, r) return } topic, err := topics.CascadeGet(tid) if err == ErrNoRows { - PreError("The topic you tried to pin doesn't exist.",w,r) + PreError("The topic you tried to pin doesn't exist.", w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - ok := SimpleForumSessionCheck(w,r,&user,topic.ParentID) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, topic.ParentID) if !ok { return } if !user.Perms.ViewTopic || !user.Perms.PinTopic { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } _, err = stick_topic_stmt.Exec(tid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - err = addModLog("stick",tid,"topic",ipaddress,user.ID) + err = addModLog("stick", tid, "topic", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = create_action_reply_stmt.Exec(tid,"stick",ipaddress,user.ID) + _, err = create_action_reply_stmt.Exec(tid, "stick", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } err = topics.Load(tid) if err != nil { - LocalError("This topic doesn't exist!",w,r,user) + LocalError("This topic doesn't exist!", w, r, user) return } - http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) + http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther) } func route_unstick_topic(w http.ResponseWriter, r *http.Request, user User) { tid, err := strconv.Atoi(r.URL.Path[len("/topic/unstick/submit/"):]) if err != nil { - PreError("The provided TopicID is not a valid number.",w,r) + PreError("The provided TopicID is not a valid number.", w, r) return } topic, err := topics.CascadeGet(tid) if err == ErrNoRows { - PreError("The topic you tried to unpin doesn't exist.",w,r) + PreError("The topic you tried to unpin doesn't exist.", w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - ok := SimpleForumSessionCheck(w,r,&user,topic.ParentID) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, topic.ParentID) if !ok { return } if !user.Perms.ViewTopic || !user.Perms.PinTopic { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } _, err = unstick_topic_stmt.Exec(tid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - err = addModLog("unstick",tid,"topic",ipaddress,user.ID) + err = addModLog("unstick", tid, "topic", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = create_action_reply_stmt.Exec(tid,"unstick",ipaddress,user.ID) + _, err = create_action_reply_stmt.Exec(tid, "unstick", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } err = topics.Load(tid) if err != nil { - LocalError("This topic doesn't exist!",w,r,user) + LocalError("This topic doesn't exist!", w, r, user) return } - http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) + http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther) } func route_reply_edit_submit(w http.ResponseWriter, r *http.Request, user User) { err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } - is_js := r.PostFormValue("js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("js") == "1") rid, err := strconv.Atoi(r.URL.Path[len("/reply/edit/submit/"):]) if err != nil { - PreErrorJSQ("The provided Reply ID is not a valid number.",w,r,is_js) + PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs) return } - content := html.EscapeString(preparse_message(r.PostFormValue("edit_item"))) - _, err = edit_reply_stmt.Exec(content, parse_message(content), rid) + content := html.EscapeString(preparseMessage(r.PostFormValue("edit_item"))) + _, err = edit_reply_stmt.Exec(content, parseMessage(content), rid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } @@ -315,118 +313,117 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request, user User) var tid int err = get_reply_tid_stmt.QueryRow(rid).Scan(&tid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } var fid int err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid) if err == ErrNoRows { - PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js) + PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs) return } else if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - ok := SimpleForumSessionCheck(w,r,&user,fid) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, fid) if !ok { return } if !user.Perms.ViewTopic || !user.Perms.EditReply { - NoPermissionsJSQ(w,r,user,is_js) + NoPermissionsJSQ(w, r, user, isJs) return } - if is_js == "0" { - http.Redirect(w,r, "/topic/" + strconv.Itoa(tid) + "#reply-" + strconv.Itoa(rid), http.StatusSeeOther) + if !isJs { + http.Redirect(w, r, "/topic/"+strconv.Itoa(tid)+"#reply-"+strconv.Itoa(rid), http.StatusSeeOther) } else { - w.Write(success_json_bytes) + w.Write(successJSONBytes) } } func route_reply_delete_submit(w http.ResponseWriter, r *http.Request, user User) { err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } - is_js := r.PostFormValue("is_js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("isJs") == "1") rid, err := strconv.Atoi(r.URL.Path[len("/reply/delete/submit/"):]) if err != nil { - PreErrorJSQ("The provided Reply ID is not a valid number.",w,r,is_js) + PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs) return } - reply, err := get_reply(rid) + reply, err := getReply(rid) if err == ErrNoRows { - PreErrorJSQ("The reply you tried to delete doesn't exist.",w,r,is_js) + PreErrorJSQ("The reply you tried to delete doesn't exist.", w, r, isJs) return } else if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } var fid int err = get_topic_fid_stmt.QueryRow(reply.ParentID).Scan(&fid) if err == ErrNoRows { - PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js) + PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs) return } else if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - ok := SimpleForumSessionCheck(w,r,&user,fid) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, fid) if !ok { return } if !user.Perms.ViewTopic || !user.Perms.DeleteReply { - NoPermissionsJSQ(w,r,user,is_js) + NoPermissionsJSQ(w, r, user, isJs) return } _, err = delete_reply_stmt.Exec(rid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } //log.Print("Reply #" + strconv.Itoa(rid) + " was deleted by User #" + strconv.Itoa(user.ID)) - if is_js == "0" { + if !isJs { //http.Redirect(w,r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther) } else { - w.Write(success_json_bytes) + w.Write(successJSONBytes) } - wcount := word_count(reply.Content) + wcount := wordCount(reply.Content) err = decrease_post_user_stats(wcount, reply.CreatedBy, false, user) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - _, err = remove_replies_from_topic_stmt.Exec(1,reply.ParentID) + _, err = remove_replies_from_topic_stmt.Exec(1, reply.ParentID) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - err = addModLog("delete",reply.ParentID,"reply",ipaddress,user.ID) + err = addModLog("delete", reply.ParentID, "reply", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } err = topics.Load(reply.ParentID) if err != nil { - LocalError("This topic no longer exists!",w,r,user) + LocalError("This topic no longer exists!", w, r, user) return } } @@ -434,17 +431,14 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request, user User func route_profile_reply_edit_submit(w http.ResponseWriter, r *http.Request, user User) { err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } - is_js := r.PostFormValue("js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("js") == "1") rid, err := strconv.Atoi(r.URL.Path[len("/profile/reply/edit/submit/"):]) if err != nil { - LocalErrorJSQ("The provided Reply ID is not a valid number.",w,r,user,is_js) + LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, user, isJs) return } @@ -452,72 +446,173 @@ func route_profile_reply_edit_submit(w http.ResponseWriter, r *http.Request, use var uid int err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } if user.ID != uid && !user.Perms.EditReply { - NoPermissionsJSQ(w,r,user,is_js) + NoPermissionsJSQ(w, r, user, isJs) return } - content := html.EscapeString(preparse_message(r.PostFormValue("edit_item"))) - _, err = edit_profile_reply_stmt.Exec(content, parse_message(content), rid) + content := html.EscapeString(preparseMessage(r.PostFormValue("edit_item"))) + _, err = edit_profile_reply_stmt.Exec(content, parseMessage(content), rid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - if is_js == "0" { - http.Redirect(w,r,"/user/" + strconv.Itoa(uid) + "#reply-" + strconv.Itoa(rid), http.StatusSeeOther) + if !isJs { + http.Redirect(w, r, "/user/"+strconv.Itoa(uid)+"#reply-"+strconv.Itoa(rid), http.StatusSeeOther) } else { - w.Write(success_json_bytes) + w.Write(successJSONBytes) } } func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request, user User) { err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } - is_js := r.PostFormValue("is_js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("isJs") == "1") rid, err := strconv.Atoi(r.URL.Path[len("/profile/reply/delete/submit/"):]) if err != nil { - LocalErrorJSQ("The provided Reply ID is not a valid number.",w,r,user,is_js) + LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, user, isJs) return } var uid int err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid) if err == ErrNoRows { - LocalErrorJSQ("The reply you tried to delete doesn't exist.",w,r,user,is_js) + LocalErrorJSQ("The reply you tried to delete doesn't exist.", w, r, user, isJs) return } else if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } if user.ID != uid && !user.Perms.DeleteReply { - NoPermissionsJSQ(w,r,user,is_js) + NoPermissionsJSQ(w, r, user, isJs) return } _, err = delete_profile_reply_stmt.Exec(rid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } //log.Print("The profile post '" + strconv.Itoa(rid) + "' was deleted by User #" + strconv.Itoa(user.ID)) - if is_js == "0" { + if !isJs { //http.Redirect(w,r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther) } else { - w.Write(success_json_bytes) + w.Write(successJSONBytes) + } +} + +func route_ips(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) + if !ok { + return + } + if !user.Perms.ViewIPs { + NoPermissions(w, r, user) + return + } + + ip := html.EscapeString(r.URL.Path[len("/users/ips/"):]) + var uid int + var reqUserList map[int]bool = make(map[int]bool) + + rows, err := find_users_by_ip_users_stmt.Query(ip) + if err != nil { + InternalError(err, w) + return + } + defer rows.Close() + + for rows.Next() { + err := rows.Scan(&uid) + if err != nil { + InternalError(err, w) + return + } + reqUserList[uid] = true + } + err = rows.Err() + if err != nil { + InternalError(err, w) + return + } + + rows2, err := find_users_by_ip_topics_stmt.Query(ip) + if err != nil { + InternalError(err, w) + return + } + defer rows2.Close() + + for rows2.Next() { + err := rows2.Scan(&uid) + if err != nil { + InternalError(err, w) + return + } + reqUserList[uid] = true + } + err = rows2.Err() + if err != nil { + InternalError(err, w) + return + } + + rows3, err := find_users_by_ip_replies_stmt.Query(ip) + if err != nil { + InternalError(err, w) + return + } + defer rows3.Close() + + for rows3.Next() { + err := rows3.Scan(&uid) + if err != nil { + InternalError(err, w) + return + } + reqUserList[uid] = true + } + err = rows3.Err() + if err != nil { + InternalError(err, w) + return + } + + // Convert the user ID map to a slice, then bulk load the users + var idSlice []int = make([]int, len(reqUserList)) + var i int + for userID := range reqUserList { + idSlice[i] = userID + i++ + } + + // TO-DO: What if a user is deleted via the Control Panel? + userList, err := users.BulkCascadeGetMap(idSlice) + if err != nil { + InternalError(err, w) + return + } + + pi := IPSearchPage{"IP Search", user, headerVars, userList, ip} + if preRenderHooks["pre_render_ips"] != nil { + if runPreRenderHook("pre_render_ips", w, r, &user, &pi) { + return + } + } + err = templates.ExecuteTemplate(w, "ip-search.html", pi) + if err != nil { + InternalError(err, w) } } @@ -552,8 +647,8 @@ func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request, u yousure := AreYouSure{"/users/ban/submit/" + strconv.Itoa(uid),confirm_msg} pi := Page{"Ban User",user,headerVars,tList,yousure} - if pre_render_hooks["pre_render_ban"] != nil { - if run_pre_render_hook("pre_render_ban", w, r, &user, &pi) { + if preRenderHooks["pre_render_ban"] != nil { + if runPreRenderHook("pre_render_ban", w, r, &user, &pi) { return } } @@ -562,17 +657,17 @@ func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request, u func route_ban_submit(w http.ResponseWriter, r *http.Request, user User) { if !user.Perms.BanUsers { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } uid, err := strconv.Atoi(r.URL.Path[len("/users/ban/submit/"):]) if err != nil { - LocalError("The provided User ID is not a valid number.",w,r,user) + LocalError("The provided User ID is not a valid number.", w, r, user) return } /*if uid == -2 { @@ -582,189 +677,189 @@ func route_ban_submit(w http.ResponseWriter, r *http.Request, user User) { targetUser, err := users.CascadeGet(uid) if err == ErrNoRows { - LocalError("The user you're trying to ban no longer exists.",w,r,user) + LocalError("The user you're trying to ban no longer exists.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - if targetUser.Is_Super_Admin || targetUser.Is_Admin || targetUser.Is_Mod { - LocalError("You may not ban another staff member.",w,r,user) + if targetUser.IsSuperAdmin || targetUser.IsAdmin || targetUser.IsMod { + LocalError("You may not ban another staff member.", w, r, user) return } if uid == user.ID { - LocalError("Why are you trying to ban yourself? Stop that.",w,r,user) + LocalError("Why are you trying to ban yourself? Stop that.", w, r, user) return } - if targetUser.Is_Banned { - LocalError("The user you're trying to unban is already banned.",w,r,user) + if targetUser.IsBanned { + LocalError("The user you're trying to unban is already banned.", w, r, user) return } - duration_days, err := strconv.Atoi(r.FormValue("ban-duration-days")) + durationDays, err := strconv.Atoi(r.FormValue("ban-duration-days")) if err != nil { - LocalError("You can only use whole numbers for the number of days",w,r,user) + LocalError("You can only use whole numbers for the number of days", w, r, user) return } - duration_weeks, err := strconv.Atoi(r.FormValue("ban-duration-weeks")) + durationWeeks, err := strconv.Atoi(r.FormValue("ban-duration-weeks")) if err != nil { - LocalError("You can only use whole numbers for the number of weeks",w,r,user) + LocalError("You can only use whole numbers for the number of weeks", w, r, user) return } - duration_months, err := strconv.Atoi(r.FormValue("ban-duration-months")) + durationMonths, err := strconv.Atoi(r.FormValue("ban-duration-months")) if err != nil { - LocalError("You can only use whole numbers for the number of months",w,r,user) + LocalError("You can only use whole numbers for the number of months", w, r, user) return } var duration time.Duration - if duration_days > 1 && duration_weeks > 1 && duration_months > 1 { + if durationDays > 1 && durationWeeks > 1 && durationMonths > 1 { duration, _ = time.ParseDuration("0") } else { var seconds int - seconds += duration_days * day - seconds += duration_weeks * week - seconds += duration_months * month + seconds += durationDays * day + seconds += durationWeeks * week + seconds += durationMonths * month duration, _ = time.ParseDuration(strconv.Itoa(seconds) + "s") } - err = targetUser.Ban(duration,user.ID) + err = targetUser.Ban(duration, user.ID) if err == ErrNoRows { - LocalError("The user you're trying to ban no longer exists.",w,r,user) + LocalError("The user you're trying to ban no longer exists.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - err = addModLog("ban",uid,"user",ipaddress,user.ID) + err = addModLog("ban", uid, "user", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/user/" + strconv.Itoa(uid),http.StatusSeeOther) + http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther) } func route_unban(w http.ResponseWriter, r *http.Request, user User) { if !user.Perms.BanUsers { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } uid, err := strconv.Atoi(r.URL.Path[len("/users/unban/"):]) if err != nil { - LocalError("The provided User ID is not a valid number.",w,r,user) + LocalError("The provided User ID is not a valid number.", w, r, user) return } targetUser, err := users.CascadeGet(uid) if err == ErrNoRows { - LocalError("The user you're trying to unban no longer exists.",w,r,user) + LocalError("The user you're trying to unban no longer exists.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - if !targetUser.Is_Banned { - LocalError("The user you're trying to unban isn't banned.",w,r,user) + if !targetUser.IsBanned { + LocalError("The user you're trying to unban isn't banned.", w, r, user) return } err = targetUser.Unban() if err == ErrNoRows { - LocalError("The user you're trying to unban no longer exists.",w,r,user) + LocalError("The user you're trying to unban no longer exists.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - err = addModLog("unban",uid,"user",ipaddress,user.ID) + err = addModLog("unban", uid, "user", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/user/" + strconv.Itoa(uid),http.StatusSeeOther) + http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther) } func route_activate(w http.ResponseWriter, r *http.Request, user User) { if !user.Perms.ActivateUsers { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(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) + LocalError("The provided User ID is not a valid number.", w, r, user) return } var active bool err = get_user_active_stmt.QueryRow(uid).Scan(&active) if err == ErrNoRows { - LocalError("The account you're trying to activate no longer exists.",w,r,user) + LocalError("The account you're trying to activate no longer exists.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } if active { - LocalError("The account you're trying to activate has already been activated.",w,r,user) + 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) + InternalError(err, w) return } _, err = change_group_stmt.Exec(config.DefaultGroup, uid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - err = addModLog("activate",uid,"user",ipaddress,user.ID) + err = addModLog("activate", uid, "user", ipaddress, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } err = users.Load(uid) if err != nil { - LocalError("This user no longer exists!",w,r,user) + LocalError("This user no longer exists!", w, r, user) return } - http.Redirect(w,r,"/user/" + strconv.Itoa(uid),http.StatusSeeOther) + http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther) } diff --git a/mysql.go b/mysql.go index 37efc475..a63b1110 100644 --- a/mysql.go +++ b/mysql.go @@ -4,31 +4,35 @@ package main import "log" + //import "time" import "database/sql" import _ "github.com/go-sql-driver/mysql" import "./query_gen/lib" -var db_collation string = "utf8mb4_general_ci" +var dbCollation = "utf8mb4_general_ci" var get_activity_feed_by_watcher_stmt *sql.Stmt var get_activity_count_by_watcher_stmt *sql.Stmt var todays_post_count_stmt *sql.Stmt var todays_topic_count_stmt *sql.Stmt var todays_report_count_stmt *sql.Stmt var todays_newuser_count_stmt *sql.Stmt +var find_users_by_ip_users_stmt *sql.Stmt +var find_users_by_ip_topics_stmt *sql.Stmt +var find_users_by_ip_replies_stmt *sql.Stmt func init() { - db_adapter = "mysql" + dbAdapter = "mysql" } -func _init_database() (err error) { +func _initDatabase() (err error) { var _dbpassword string - if(db_config.Password != ""){ + if db_config.Password != "" { _dbpassword = ":" + db_config.Password } // Open the database connection - db, err = sql.Open("mysql", db_config.Username + _dbpassword + "@tcp(" + db_config.Host + ":" + db_config.Port + ")/" + db_config.Dbname + "?collation=" + db_collation) + db, err = sql.Open("mysql", db_config.Username+_dbpassword+"@tcp("+db_config.Host+":"+db_config.Port+")/"+db_config.Dbname+"?collation="+dbCollation) if err != nil { return err } @@ -40,7 +44,7 @@ func _init_database() (err error) { } // Fetch the database version - db.QueryRow("SELECT VERSION()").Scan(&db_version) + db.QueryRow("SELECT VERSION()").Scan(&dbVersion) // Set the number of max open connections db.SetMaxOpenConns(64) @@ -62,6 +66,7 @@ func _init_database() (err error) { return err } + // TO-DO: Is there a less noisy way of doing this for tests? log.Print("Preparing get_activity_feed_by_watcher statement.") get_activity_feed_by_watcher_stmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ? ORDER BY activity_stream.asid ASC LIMIT 8") if err != nil { @@ -98,5 +103,19 @@ func _init_database() (err error) { return err } - return nil + log.Print("Preparing find_users_by_ip_users statement.") + find_users_by_ip_users_stmt, err = db.Prepare("select uid from users where last_ip = ?") + if err != nil { + return err + } + + log.Print("Preparing find_users_by_ip_topics statement.") + find_users_by_ip_topics_stmt, err = db.Prepare("select uid from users where uid in(select createdBy from topics where ipaddress = ?)") + if err != nil { + return err + } + + log.Print("Preparing find_users_by_ip_replies statement.") + find_users_by_ip_replies_stmt, err = db.Prepare("select uid from users where uid in(select createdBy from replies where ipaddress = ?)") + return err } diff --git a/no_websockets.go b/no_websockets.go index 62410c28..edc901d7 100644 --- a/no_websockets.go +++ b/no_websockets.go @@ -5,11 +5,10 @@ package main import "errors" import "net/http" -var ws_hub WS_Hub -var ws_nouser error = errors.New("This user isn't connected via WebSockets") +var wsHub WS_Hub +var wsNouser error = errors.New("This user isn't connected via WebSockets") -type WS_Hub struct -{ +type WS_Hub struct { } func (_ *WS_Hub) guest_count() int { @@ -25,15 +24,15 @@ func (hub *WS_Hub) broadcast_message(_ string) error { } func (hub *WS_Hub) push_message(_ int, _ string) error { - return ws_nouser + return wsNouser } -func(hub *WS_Hub) push_alert(_ int, _ int, _ string, _ string, _ int, _ int, _ int) error { - return ws_nouser +func (hub *WS_Hub) push_alert(_ int, _ int, _ string, _ string, _ int, _ int, _ int) error { + return wsNouser } -func(hub *WS_Hub) push_alerts(_ []int, _ int, _ string, _ string, _ int, _ int, _ int) error { - return ws_nouser +func (hub *WS_Hub) push_alerts(_ []int, _ int, _ string, _ string, _ int, _ int, _ int) error { + return wsNouser } func route_websockets(_ http.ResponseWriter, _ *http.Request, _ User) { diff --git a/pages.go b/pages.go index 950da411..b78031fe 100644 --- a/pages.go +++ b/pages.go @@ -8,27 +8,26 @@ import "strconv" import "regexp" import "html/template" -type HeaderVars struct -{ - NoticeList []string - Scripts []string +type HeaderVars struct { + NoticeList []string + Scripts []string Stylesheets []string - Widgets PageWidgets - Site *Site - Settings map[string]interface{} - ExtData ExtData + Widgets PageWidgets + Site *Site + Settings map[string]interface{} + ThemeName string + ExtData ExtData } // TO-DO: Add this to routes which don't use templates. E.g. Json APIs. -type HeaderLite struct -{ - Site *Site +type HeaderLite struct { + Site *Site Settings SettingBox + ExtData ExtData } -type PageWidgets struct -{ - LeftSidebar template.HTML +type PageWidgets struct { + LeftSidebar template.HTML RightSidebar template.HTML } @@ -37,444 +36,413 @@ type PageWidgets struct items map[string]interface{} // Key: pluginname }*/ -type ExtData struct -{ +// TO-DO: Add a ExtDataHolder interface with methods for manipulating the contents? +type ExtData struct { items map[string]interface{} // Key: pluginname sync.RWMutex } -type Page struct -{ - Title string +type Page struct { + Title string CurrentUser User - Header HeaderVars - ItemList []interface{} - Something interface{} + Header *HeaderVars + ItemList []interface{} + Something interface{} } -type TopicPage struct -{ - Title string +type TopicPage struct { + Title string CurrentUser User - Header HeaderVars - ItemList []Reply - Topic TopicUser - Page int - LastPage int - ExtData ExtData + Header *HeaderVars + ItemList []Reply + Topic TopicUser + Page int + LastPage int } -type TopicsPage struct -{ - Title string +type TopicsPage struct { + Title string CurrentUser User - Header HeaderVars - ItemList []*TopicsRow - ExtData ExtData + Header *HeaderVars + ItemList []*TopicsRow } -type ForumPage struct -{ - Title string +type ForumPage struct { + Title string CurrentUser User - Header HeaderVars - ItemList []*TopicsRow - Forum Forum - Page int - LastPage int - ExtData ExtData + Header *HeaderVars + ItemList []*TopicsRow + Forum Forum + Page int + LastPage int } -type ForumsPage struct -{ - Title string +type ForumsPage struct { + Title string CurrentUser User - Header HeaderVars - ItemList []Forum - ExtData ExtData + Header *HeaderVars + ItemList []Forum } -type ProfilePage struct -{ - Title string - CurrentUser User - Header HeaderVars - ItemList []Reply +type ProfilePage struct { + Title string + CurrentUser User + Header *HeaderVars + ItemList []Reply ProfileOwner User - ExtData ExtData } -type CreateTopicPage struct -{ - Title string +type CreateTopicPage struct { + Title string CurrentUser User - Header HeaderVars - ItemList []Forum - FID int - ExtData ExtData + Header *HeaderVars + ItemList []Forum + FID int } -type PanelStats struct -{ - Users int - Groups int - Forums int - Settings int +type IPSearchPage struct { + Title string + CurrentUser User + Header *HeaderVars + ItemList map[int]*User + IP string +} + +type PanelStats struct { + Users int + Groups int + Forums int + Settings int WordFilters int - Themes int - Reports int + Themes int + Reports int } -type PanelPage struct -{ - Title string +type PanelPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - ItemList []interface{} - Something interface{} + Header *HeaderVars + Stats PanelStats + ItemList []interface{} + Something interface{} } -type GridElement struct -{ - ID string - Body string - Order int // For future use - Class string +type GridElement struct { + ID string + Body string + Order int // For future use + Class string Background string TextColour string - Note string + Note string } -type PanelDashboardPage struct -{ - Title string +type PanelDashboardPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - GridItems []GridElement - ExtData ExtData + Header *HeaderVars + Stats PanelStats + GridItems []GridElement } -type PanelThemesPage struct -{ - Title string - CurrentUser User - Header HeaderVars - Stats PanelStats +type PanelThemesPage struct { + Title string + CurrentUser User + Header *HeaderVars + Stats PanelStats PrimaryThemes []Theme VariantThemes []Theme - ExtData ExtData } -type PanelUserPage struct -{ - Title string +type PanelUserPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - ItemList []User - PageList []int - Page int - LastPage int - ExtData ExtData + Header *HeaderVars + Stats PanelStats + ItemList []User + PageList []int + Page int + LastPage int } -type PanelGroupPage struct -{ - Title string +type PanelGroupPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - ItemList []GroupAdmin - PageList []int - Page int - LastPage int - ExtData ExtData + Header *HeaderVars + Stats PanelStats + ItemList []GroupAdmin + PageList []int + Page int + LastPage int } -type PanelEditGroupPage struct -{ - Title string +type PanelEditGroupPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - ID int - Name string - Tag string - Rank string + Header *HeaderVars + Stats PanelStats + ID int + Name string + Tag string + Rank string DisableRank bool - ExtData ExtData } -type GroupForumPermPreset struct -{ - Group Group +type GroupForumPermPreset struct { + Group Group Preset string } -type PanelEditForumPage struct -{ - Title string +type PanelEditForumPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - ID int - Name string - Desc string - Active bool - Preset string - Groups []GroupForumPermPreset - ExtData ExtData + Header *HeaderVars + Stats PanelStats + ID int + Name string + Desc string + Active bool + Preset string + Groups []GroupForumPermPreset } -type NameLangPair struct -{ - Name string +type NameLangPair struct { + Name string LangStr string } -type NameLangToggle struct -{ - Name string +type NameLangToggle struct { + Name string LangStr string - Toggle bool + Toggle bool } -type PanelEditGroupPermsPage struct -{ - Title string +type PanelEditGroupPermsPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - ID int - Name string - LocalPerms []NameLangToggle + Header *HeaderVars + Stats PanelStats + ID int + Name string + LocalPerms []NameLangToggle GlobalPerms []NameLangToggle - ExtData ExtData } type Log struct { - Action template.HTML + Action template.HTML IPAddress string - DoneAt string + DoneAt string } -type PanelLogsPage struct -{ - Title string +type PanelLogsPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - Logs []Log - PageList []int - Page int - LastPage int - ExtData ExtData + Header *HeaderVars + Stats PanelStats + Logs []Log + PageList []int + Page int + LastPage int } -type PanelDebugPage struct -{ - Title string +type PanelDebugPage struct { + Title string CurrentUser User - Header HeaderVars - Stats PanelStats - Uptime string - OpenConns int - DBAdapter string - ExtData ExtData + Header *HeaderVars + Stats PanelStats + Uptime string + OpenConns int + DBAdapter string } -type PageSimple struct -{ - Title string +type PageSimple struct { + Title string Something interface{} } -type AreYouSure struct -{ - URL string +type AreYouSure struct { + URL string Message string } -var space_gap []byte = []byte(" ") -var http_prot_b []byte = []byte("http://") -var invalid_url []byte = []byte("[Invalid URL]") -var invalid_topic []byte = []byte("[Invalid Topic]") -var invalid_profile []byte = []byte("[Invalid Profile]") -var invalid_forum []byte = []byte("[Invalid Forum]") -var url_open []byte = []byte("") -var bytes_singlequote []byte = []byte("'") -var bytes_greaterthan []byte = []byte(">") -var url_mention []byte = []byte(" class='mention'") -var url_close []byte = []byte("") -var urlpattern string = `(?s)([ {1}])((http|https|ftp|mailto)*)(:{??)\/\/([\.a-zA-Z\/]+)([ {1}])` -var url_reg *regexp.Regexp +var spaceGap = []byte(" ") +var httpProtBytes = []byte("http://") +var invalidURL = []byte("[Invalid URL]") +var invalidTopic = []byte("[Invalid Topic]") +var invalidProfile = []byte("[Invalid Profile]") +var invalidForum = []byte("[Invalid Forum]") +var urlOpen = []byte("") +var bytesSinglequote = []byte("'") +var bytesGreaterthan = []byte(">") +var urlMention = []byte(" class='mention'") +var urlClose = []byte("") +var urlpattern = `(?s)([ {1}])((http|https|ftp|mailto)*)(:{??)\/\/([\.a-zA-Z\/]+)([ {1}])` +var urlReg *regexp.Regexp func init() { - url_reg = regexp.MustCompile(urlpattern) + urlReg = regexp.MustCompile(urlpattern) } -func shortcode_to_unicode(msg string) string { +func shortcodeToUnicode(msg string) string { //re := regexp.MustCompile(":(.):") - msg = strings.Replace(msg,":grinning:","😀",-1) - msg = strings.Replace(msg,":grin:","😁",-1) - msg = strings.Replace(msg,":joy:","😂",-1) - msg = strings.Replace(msg,":rofl:","🤣",-1) - msg = strings.Replace(msg,":smiley:","😃",-1) - msg = strings.Replace(msg,":smile:","😄",-1) - msg = strings.Replace(msg,":sweat_smile:","😅",-1) - msg = strings.Replace(msg,":laughing:","😆",-1) - msg = strings.Replace(msg,":satisfied:","😆",-1) - msg = strings.Replace(msg,":wink:","😉",-1) - msg = strings.Replace(msg,":blush:","😊",-1) - msg = strings.Replace(msg,":yum:","😋",-1) - msg = strings.Replace(msg,":sunglasses:","😎",-1) - msg = strings.Replace(msg,":heart_eyes:","😍",-1) - msg = strings.Replace(msg,":kissing_heart:","😘",-1) - msg = strings.Replace(msg,":kissing:","😗",-1) - msg = strings.Replace(msg,":kissing_smiling_eyes:","😙",-1) - msg = strings.Replace(msg,":kissing_closed_eyes:","😚",-1) - msg = strings.Replace(msg,":relaxed:","☺️",-1) - msg = strings.Replace(msg,":slight_smile:","🙂",-1) - msg = strings.Replace(msg,":hugging:","🤗",-1) - msg = strings.Replace(msg,":thinking:","🤔",-1) - msg = strings.Replace(msg,":neutral_face:","😐",-1) - msg = strings.Replace(msg,":expressionless:","😑",-1) - msg = strings.Replace(msg,":no_mouth:","😶",-1) - msg = strings.Replace(msg,":rolling_eyes:","🙄",-1) - msg = strings.Replace(msg,":smirk:","😏",-1) - msg = strings.Replace(msg,":persevere:","😣",-1) - msg = strings.Replace(msg,":disappointed_relieved:","😥",-1) - msg = strings.Replace(msg,":open_mouth:","😮",-1) - msg = strings.Replace(msg,":zipper_mouth:","🤐",-1) - msg = strings.Replace(msg,":hushed:","😯",-1) - msg = strings.Replace(msg,":sleepy:","😪",-1) - msg = strings.Replace(msg,":tired_face:","😫",-1) - msg = strings.Replace(msg,":sleeping:","😴",-1) - msg = strings.Replace(msg,":relieved:","😌",-1) - msg = strings.Replace(msg,":nerd:","🤓",-1) - msg = strings.Replace(msg,":stuck_out_tongue:","😛",-1) - msg = strings.Replace(msg,":worried:","😟",-1) - msg = strings.Replace(msg,":drooling_face:","🤤",-1) - msg = strings.Replace(msg,":disappointed:","😞",-1) - msg = strings.Replace(msg,":astonished:","😲",-1) - msg = strings.Replace(msg,":slight_frown:","🙁",-1) - msg = strings.Replace(msg,":skull_crossbones:","☠️",-1) - msg = strings.Replace(msg,":skull:","💀",-1) - msg = strings.Replace(msg,":point_up:","☝️",-1) - msg = strings.Replace(msg,":v:","✌️️",-1) - msg = strings.Replace(msg,":writing_hand:","✍️",-1) - msg = strings.Replace(msg,":heart:","❤️️",-1) - msg = strings.Replace(msg,":heart_exclamation:","❣️",-1) - msg = strings.Replace(msg,":hotsprings:","♨️",-1) - msg = strings.Replace(msg,":airplane:","✈️️",-1) - msg = strings.Replace(msg,":hourglass:","⌛",-1) - msg = strings.Replace(msg,":watch:","⌚",-1) - msg = strings.Replace(msg,":comet:","☄️",-1) - msg = strings.Replace(msg,":snowflake:","❄️",-1) - msg = strings.Replace(msg,":cloud:","☁️",-1) - msg = strings.Replace(msg,":sunny:","☀️",-1) - msg = strings.Replace(msg,":spades:","♠️",-1) - msg = strings.Replace(msg,":hearts:","♥️️",-1) - msg = strings.Replace(msg,":diamonds:","♦️",-1) - msg = strings.Replace(msg,":clubs:","♣️",-1) - msg = strings.Replace(msg,":phone:","☎️",-1) - msg = strings.Replace(msg,":telephone:","☎️",-1) - msg = strings.Replace(msg,":biohazard:","☣️",-1) - msg = strings.Replace(msg,":radioactive:","☢️",-1) - msg = strings.Replace(msg,":scissors:","✂️",-1) - msg = strings.Replace(msg,":arrow_upper_right:","↗️",-1) - msg = strings.Replace(msg,":arrow_right:","➡️",-1) - msg = strings.Replace(msg,":arrow_lower_right:","↘️",-1) - msg = strings.Replace(msg,":arrow_lower_left:","↙️",-1) - msg = strings.Replace(msg,":arrow_upper_left:","↖️",-1) - msg = strings.Replace(msg,":arrow_up_down:","↕️",-1) - msg = strings.Replace(msg,":left_right_arrow:","↔️",-1) - msg = strings.Replace(msg,":leftwards_arrow_with_hook:","↩️",-1) - msg = strings.Replace(msg,":arrow_right_hook:","↪️",-1) - msg = strings.Replace(msg,":arrow_forward:","▶️",-1) - msg = strings.Replace(msg,":arrow_backward:","◀️",-1) - msg = strings.Replace(msg,":female:","♀️",-1) - msg = strings.Replace(msg,":male:","♂️",-1) - msg = strings.Replace(msg,":ballot_box_with_check:","☑️",-1) - msg = strings.Replace(msg,":heavy_check_mark:","✔️️",-1) - msg = strings.Replace(msg,":heavy_multiplication_x:","✖️",-1) - msg = strings.Replace(msg,":pisces:","♓",-1) - msg = strings.Replace(msg,":aquarius:","♒",-1) - msg = strings.Replace(msg,":capricorn:","♑",-1) - msg = strings.Replace(msg,":sagittarius:","♐",-1) - msg = strings.Replace(msg,":scorpius:","♏",-1) - msg = strings.Replace(msg,":libra:","♎",-1) - msg = strings.Replace(msg,":virgo:","♍",-1) - msg = strings.Replace(msg,":leo:","♌",-1) - msg = strings.Replace(msg,":cancer:","♋",-1) - msg = strings.Replace(msg,":gemini:","♊",-1) - msg = strings.Replace(msg,":taurus:","♉",-1) - msg = strings.Replace(msg,":aries:","♈",-1) - msg = strings.Replace(msg,":peace:","☮️",-1) - msg = strings.Replace(msg,":eight_spoked_asterisk:","✳️",-1) - msg = strings.Replace(msg,":eight_pointed_black_star:","✴️",-1) - msg = strings.Replace(msg,":snowman2:","☃️",-1) - msg = strings.Replace(msg,":umbrella2:","☂️",-1) - msg = strings.Replace(msg,":pencil2:","✏️",-1) - msg = strings.Replace(msg,":black_nib:","✒️",-1) - msg = strings.Replace(msg,":email:","✉️",-1) - msg = strings.Replace(msg,":envelope:","✉️",-1) - msg = strings.Replace(msg,":keyboard:","⌨️",-1) - msg = strings.Replace(msg,":white_small_square:","▫️",-1) - msg = strings.Replace(msg,":black_small_square:","▪️",-1) - msg = strings.Replace(msg,":secret:","㊙️",-1) - msg = strings.Replace(msg,":congratulations:","㊗️",-1) - msg = strings.Replace(msg,":m:","Ⓜ️",-1) - msg = strings.Replace(msg,":tm:","™️️",-1) - msg = strings.Replace(msg,":registered:","®️",-1) - msg = strings.Replace(msg,":copyright:","©️",-1) - msg = strings.Replace(msg,":wavy_dash:","〰️",-1) - msg = strings.Replace(msg,":bangbang:","‼️",-1) - msg = strings.Replace(msg,":sparkle:","❇️",-1) - msg = strings.Replace(msg,":star_of_david:","✡️",-1) - msg = strings.Replace(msg,":wheel_of_dharma:","☸️",-1) - msg = strings.Replace(msg,":yin_yang:","☯️",-1) - msg = strings.Replace(msg,":cross:","✝️",-1) - msg = strings.Replace(msg,":orthodox_cross:","☦️",-1) - msg = strings.Replace(msg,":star_and_crescent:","☪️",-1) - msg = strings.Replace(msg,":frowning2:","☹️",-1) - msg = strings.Replace(msg,":information_source:","ℹ️",-1) - msg = strings.Replace(msg,":interrobang:","⁉️",-1) + msg = strings.Replace(msg, ":grinning:", "😀", -1) + msg = strings.Replace(msg, ":grin:", "😁", -1) + msg = strings.Replace(msg, ":joy:", "😂", -1) + msg = strings.Replace(msg, ":rofl:", "🤣", -1) + msg = strings.Replace(msg, ":smiley:", "😃", -1) + msg = strings.Replace(msg, ":smile:", "😄", -1) + msg = strings.Replace(msg, ":sweat_smile:", "😅", -1) + msg = strings.Replace(msg, ":laughing:", "😆", -1) + msg = strings.Replace(msg, ":satisfied:", "😆", -1) + msg = strings.Replace(msg, ":wink:", "😉", -1) + msg = strings.Replace(msg, ":blush:", "😊", -1) + msg = strings.Replace(msg, ":yum:", "😋", -1) + msg = strings.Replace(msg, ":sunglasses:", "😎", -1) + msg = strings.Replace(msg, ":heart_eyes:", "😍", -1) + msg = strings.Replace(msg, ":kissing_heart:", "😘", -1) + msg = strings.Replace(msg, ":kissing:", "😗", -1) + msg = strings.Replace(msg, ":kissing_smiling_eyes:", "😙", -1) + msg = strings.Replace(msg, ":kissing_closed_eyes:", "😚", -1) + msg = strings.Replace(msg, ":relaxed:", "☺️", -1) + msg = strings.Replace(msg, ":slight_smile:", "🙂", -1) + msg = strings.Replace(msg, ":hugging:", "🤗", -1) + msg = strings.Replace(msg, ":thinking:", "🤔", -1) + msg = strings.Replace(msg, ":neutral_face:", "😐", -1) + msg = strings.Replace(msg, ":expressionless:", "😑", -1) + msg = strings.Replace(msg, ":no_mouth:", "😶", -1) + msg = strings.Replace(msg, ":rolling_eyes:", "🙄", -1) + msg = strings.Replace(msg, ":smirk:", "😏", -1) + msg = strings.Replace(msg, ":persevere:", "😣", -1) + msg = strings.Replace(msg, ":disappointed_relieved:", "😥", -1) + msg = strings.Replace(msg, ":open_mouth:", "😮", -1) + msg = strings.Replace(msg, ":zipper_mouth:", "🤐", -1) + msg = strings.Replace(msg, ":hushed:", "😯", -1) + msg = strings.Replace(msg, ":sleepy:", "😪", -1) + msg = strings.Replace(msg, ":tired_face:", "😫", -1) + msg = strings.Replace(msg, ":sleeping:", "😴", -1) + msg = strings.Replace(msg, ":relieved:", "😌", -1) + msg = strings.Replace(msg, ":nerd:", "🤓", -1) + msg = strings.Replace(msg, ":stuck_out_tongue:", "😛", -1) + msg = strings.Replace(msg, ":worried:", "😟", -1) + msg = strings.Replace(msg, ":drooling_face:", "🤤", -1) + msg = strings.Replace(msg, ":disappointed:", "😞", -1) + msg = strings.Replace(msg, ":astonished:", "😲", -1) + msg = strings.Replace(msg, ":slight_frown:", "🙁", -1) + msg = strings.Replace(msg, ":skull_crossbones:", "☠️", -1) + msg = strings.Replace(msg, ":skull:", "💀", -1) + msg = strings.Replace(msg, ":point_up:", "☝️", -1) + msg = strings.Replace(msg, ":v:", "✌️️", -1) + msg = strings.Replace(msg, ":writing_hand:", "✍️", -1) + msg = strings.Replace(msg, ":heart:", "❤️️", -1) + msg = strings.Replace(msg, ":heart_exclamation:", "❣️", -1) + msg = strings.Replace(msg, ":hotsprings:", "♨️", -1) + msg = strings.Replace(msg, ":airplane:", "✈️️", -1) + msg = strings.Replace(msg, ":hourglass:", "⌛", -1) + msg = strings.Replace(msg, ":watch:", "⌚", -1) + msg = strings.Replace(msg, ":comet:", "☄️", -1) + msg = strings.Replace(msg, ":snowflake:", "❄️", -1) + msg = strings.Replace(msg, ":cloud:", "☁️", -1) + msg = strings.Replace(msg, ":sunny:", "☀️", -1) + msg = strings.Replace(msg, ":spades:", "♠️", -1) + msg = strings.Replace(msg, ":hearts:", "♥️️", -1) + msg = strings.Replace(msg, ":diamonds:", "♦️", -1) + msg = strings.Replace(msg, ":clubs:", "♣️", -1) + msg = strings.Replace(msg, ":phone:", "☎️", -1) + msg = strings.Replace(msg, ":telephone:", "☎️", -1) + msg = strings.Replace(msg, ":biohazard:", "☣️", -1) + msg = strings.Replace(msg, ":radioactive:", "☢️", -1) + msg = strings.Replace(msg, ":scissors:", "✂️", -1) + msg = strings.Replace(msg, ":arrow_upper_right:", "↗️", -1) + msg = strings.Replace(msg, ":arrow_right:", "➡️", -1) + msg = strings.Replace(msg, ":arrow_lower_right:", "↘️", -1) + msg = strings.Replace(msg, ":arrow_lower_left:", "↙️", -1) + msg = strings.Replace(msg, ":arrow_upper_left:", "↖️", -1) + msg = strings.Replace(msg, ":arrow_up_down:", "↕️", -1) + msg = strings.Replace(msg, ":left_right_arrow:", "↔️", -1) + msg = strings.Replace(msg, ":leftwards_arrow_with_hook:", "↩️", -1) + msg = strings.Replace(msg, ":arrow_right_hook:", "↪️", -1) + msg = strings.Replace(msg, ":arrow_forward:", "▶️", -1) + msg = strings.Replace(msg, ":arrow_backward:", "◀️", -1) + msg = strings.Replace(msg, ":female:", "♀️", -1) + msg = strings.Replace(msg, ":male:", "♂️", -1) + msg = strings.Replace(msg, ":ballot_box_with_check:", "☑️", -1) + msg = strings.Replace(msg, ":heavy_check_mark:", "✔️️", -1) + msg = strings.Replace(msg, ":heavy_multiplication_x:", "✖️", -1) + msg = strings.Replace(msg, ":pisces:", "♓", -1) + msg = strings.Replace(msg, ":aquarius:", "♒", -1) + msg = strings.Replace(msg, ":capricorn:", "♑", -1) + msg = strings.Replace(msg, ":sagittarius:", "♐", -1) + msg = strings.Replace(msg, ":scorpius:", "♏", -1) + msg = strings.Replace(msg, ":libra:", "♎", -1) + msg = strings.Replace(msg, ":virgo:", "♍", -1) + msg = strings.Replace(msg, ":leo:", "♌", -1) + msg = strings.Replace(msg, ":cancer:", "♋", -1) + msg = strings.Replace(msg, ":gemini:", "♊", -1) + msg = strings.Replace(msg, ":taurus:", "♉", -1) + msg = strings.Replace(msg, ":aries:", "♈", -1) + msg = strings.Replace(msg, ":peace:", "☮️", -1) + msg = strings.Replace(msg, ":eight_spoked_asterisk:", "✳️", -1) + msg = strings.Replace(msg, ":eight_pointed_black_star:", "✴️", -1) + msg = strings.Replace(msg, ":snowman2:", "☃️", -1) + msg = strings.Replace(msg, ":umbrella2:", "☂️", -1) + msg = strings.Replace(msg, ":pencil2:", "✏️", -1) + msg = strings.Replace(msg, ":black_nib:", "✒️", -1) + msg = strings.Replace(msg, ":email:", "✉️", -1) + msg = strings.Replace(msg, ":envelope:", "✉️", -1) + msg = strings.Replace(msg, ":keyboard:", "⌨️", -1) + msg = strings.Replace(msg, ":white_small_square:", "▫️", -1) + msg = strings.Replace(msg, ":black_small_square:", "▪️", -1) + msg = strings.Replace(msg, ":secret:", "㊙️", -1) + msg = strings.Replace(msg, ":congratulations:", "㊗️", -1) + msg = strings.Replace(msg, ":m:", "Ⓜ️", -1) + msg = strings.Replace(msg, ":tm:", "™️️", -1) + msg = strings.Replace(msg, ":registered:", "®️", -1) + msg = strings.Replace(msg, ":copyright:", "©️", -1) + msg = strings.Replace(msg, ":wavy_dash:", "〰️", -1) + msg = strings.Replace(msg, ":bangbang:", "‼️", -1) + msg = strings.Replace(msg, ":sparkle:", "❇️", -1) + msg = strings.Replace(msg, ":star_of_david:", "✡️", -1) + msg = strings.Replace(msg, ":wheel_of_dharma:", "☸️", -1) + msg = strings.Replace(msg, ":yin_yang:", "☯️", -1) + msg = strings.Replace(msg, ":cross:", "✝️", -1) + msg = strings.Replace(msg, ":orthodox_cross:", "☦️", -1) + msg = strings.Replace(msg, ":star_and_crescent:", "☪️", -1) + msg = strings.Replace(msg, ":frowning2:", "☹️", -1) + msg = strings.Replace(msg, ":information_source:", "ℹ️", -1) + msg = strings.Replace(msg, ":interrobang:", "⁉️", -1) return msg } -func preparse_message(msg string) string { +func preparseMessage(msg string) string { if sshooks["preparse_preassign"] != nil { - msg = run_sshook("preparse_preassign", msg) + msg = runSshook("preparse_preassign", msg) } - return shortcode_to_unicode(msg) + return shortcodeToUnicode(msg) } -func parse_message(msg string/*, user User*/) string { - msg = strings.Replace(msg,":)","😀",-1) - msg = strings.Replace(msg,":(","😞",-1) - msg = strings.Replace(msg,":D","😃",-1) - msg = strings.Replace(msg,":P","😛",-1) - msg = strings.Replace(msg,":O","😲",-1) - msg = strings.Replace(msg,":p","😛",-1) - msg = strings.Replace(msg,":o","😲",-1) +func parseMessage(msg string /*, user User*/) string { + msg = strings.Replace(msg, ":)", "😀", -1) + msg = strings.Replace(msg, ":(", "😞", -1) + msg = strings.Replace(msg, ":D", "😃", -1) + msg = strings.Replace(msg, ":P", "😛", -1) + msg = strings.Replace(msg, ":O", "😲", -1) + msg = strings.Replace(msg, ":p", "😛", -1) + msg = strings.Replace(msg, ":o", "😲", -1) //msg = url_reg.ReplaceAllString(msg,"$2$3//$4") // Word filter list. E.g. Swear words and other things the admins don't like wordFilters := wordFilterBox.Load().(WordFilterBox) for _, filter := range wordFilters { - msg = strings.Replace(msg,filter.Find,filter.Replacement,-1) + msg = strings.Replace(msg, filter.Find, filter.Replacement, -1) } // Search for URLs, mentions and hashlinks in the messages... //log.Print("Parser Loop!") var msgbytes = []byte(msg) var outbytes []byte - msgbytes = append(msgbytes,space_gap...) + msgbytes = append(msgbytes, spaceGap...) //log.Print(`"`+string(msgbytes)+`"`) lastItem := 0 i := 0 @@ -489,36 +457,36 @@ func parse_message(msg string/*, user User*/) string { // log.Print("string(msgbytes[i])",string(msgbytes[i])) //} //log.Print("End Index") - if (i==0 && (msgbytes[0] > 32)) || ((msgbytes[i] < 33) && (msgbytes[i + 1] > 32)) { + if (i == 0 && (msgbytes[0] > 32)) || ((msgbytes[i] < 33) && (msgbytes[i+1] > 32)) { //log.Print("IN") //log.Print(msgbytes[i]) if (i != 0) || msgbytes[i] < 33 { i++ } - if msgbytes[i]=='#' { + if msgbytes[i] == '#' { //log.Print("IN #") - if bytes.Equal(msgbytes[i+1:i+5],[]byte("tid-")) { - outbytes = append(outbytes,msgbytes[lastItem:i]...) + if bytes.Equal(msgbytes[i+1:i+5], []byte("tid-")) { + outbytes = append(outbytes, msgbytes[lastItem:i]...) i += 5 start := i - tid, int_len := coerce_int_bytes(msgbytes[start:]) - i += int_len + tid, intLen := coerceIntBytes(msgbytes[start:]) + i += intLen topic, err := topics.CascadeGet(tid) if err != nil || !fstore.Exists(topic.ParentID) { - outbytes = append(outbytes,invalid_topic...) + outbytes = append(outbytes, invalidTopic...) lastItem = i continue } - outbytes = append(outbytes, url_open...) - var url_bit []byte = []byte(build_topic_url("",tid)) - outbytes = append(outbytes, url_bit...) - outbytes = append(outbytes, url_open2...) - var tid_bit []byte = []byte("#tid-" + strconv.Itoa(tid)) - outbytes = append(outbytes, tid_bit...) - outbytes = append(outbytes, url_close...) + outbytes = append(outbytes, urlOpen...) + var urlBit = []byte(buildTopicURL("", tid)) + outbytes = append(outbytes, urlBit...) + outbytes = append(outbytes, urlOpen2...) + var tidBit = []byte("#tid-" + strconv.Itoa(tid)) + outbytes = append(outbytes, tidBit...) + outbytes = append(outbytes, urlClose...) lastItem = i //log.Print("string(msgbytes)",string(msgbytes)) @@ -527,76 +495,76 @@ func parse_message(msg string/*, user User*/) string { //log.Print(lastItem - 1) //log.Print(msgbytes[lastItem]) //log.Print(lastItem) - } else if bytes.Equal(msgbytes[i+1:i+5],[]byte("rid-")) { - outbytes = append(outbytes,msgbytes[lastItem:i]...) + } else if bytes.Equal(msgbytes[i+1:i+5], []byte("rid-")) { + outbytes = append(outbytes, msgbytes[lastItem:i]...) i += 5 start := i - rid, int_len := coerce_int_bytes(msgbytes[start:]) - i += int_len + rid, intLen := coerceIntBytes(msgbytes[start:]) + i += intLen - topic, err := get_topic_by_reply(rid) + topic, err := getTopicByReply(rid) if err != nil || !fstore.Exists(topic.ParentID) { - outbytes = append(outbytes,invalid_topic...) + outbytes = append(outbytes, invalidTopic...) lastItem = i continue } - outbytes = append(outbytes, url_open...) - var url_bit []byte = []byte(build_topic_url("",topic.ID)) - outbytes = append(outbytes, url_bit...) - outbytes = append(outbytes, url_open2...) - var rid_bit []byte = []byte("#rid-" + strconv.Itoa(rid)) - outbytes = append(outbytes, rid_bit...) - outbytes = append(outbytes, url_close...) + outbytes = append(outbytes, urlOpen...) + var urlBit = []byte(buildTopicURL("", topic.ID)) + outbytes = append(outbytes, urlBit...) + outbytes = append(outbytes, urlOpen2...) + var ridBit = []byte("#rid-" + strconv.Itoa(rid)) + outbytes = append(outbytes, ridBit...) + outbytes = append(outbytes, urlClose...) lastItem = i - } else if bytes.Equal(msgbytes[i+1:i+5],[]byte("fid-")) { - outbytes = append(outbytes,msgbytes[lastItem:i]...) + } else if bytes.Equal(msgbytes[i+1:i+5], []byte("fid-")) { + outbytes = append(outbytes, msgbytes[lastItem:i]...) i += 5 start := i - fid, int_len := coerce_int_bytes(msgbytes[start:]) - i += int_len + fid, intLen := coerceIntBytes(msgbytes[start:]) + i += intLen if !fstore.Exists(fid) { - outbytes = append(outbytes,invalid_forum...) + outbytes = append(outbytes, invalidForum...) lastItem = i continue } - outbytes = append(outbytes, url_open...) - var url_bit []byte = []byte(build_forum_url("",fid)) - outbytes = append(outbytes, url_bit...) - outbytes = append(outbytes, url_open2...) - var fid_bit []byte = []byte("#fid-" + strconv.Itoa(fid)) - outbytes = append(outbytes, fid_bit...) - outbytes = append(outbytes, url_close...) + outbytes = append(outbytes, urlOpen...) + var urlBit = []byte(buildForumUrl("", fid)) + outbytes = append(outbytes, urlBit...) + outbytes = append(outbytes, urlOpen2...) + var fidBit = []byte("#fid-" + strconv.Itoa(fid)) + outbytes = append(outbytes, fidBit...) + outbytes = append(outbytes, urlClose...) lastItem = i } else { // TO-DO: Forum Shortcode Link } - } else if msgbytes[i]=='@' { + } else if msgbytes[i] == '@' { //log.Print("IN @") - outbytes = append(outbytes,msgbytes[lastItem:i]...) + outbytes = append(outbytes, msgbytes[lastItem:i]...) i++ start := i - uid, int_len := coerce_int_bytes(msgbytes[start:]) - i += int_len + uid, intLen := coerceIntBytes(msgbytes[start:]) + i += intLen menUser, err := users.CascadeGet(uid) if err != nil { - outbytes = append(outbytes,invalid_profile...) + outbytes = append(outbytes, invalidProfile...) lastItem = i continue } - outbytes = append(outbytes, url_open...) - var url_bit []byte = []byte(menUser.Link) - outbytes = append(outbytes, url_bit...) - outbytes = append(outbytes, bytes_singlequote...) - outbytes = append(outbytes, url_mention...) - outbytes = append(outbytes, bytes_greaterthan...) - var uid_bit []byte = []byte("@" + menUser.Name) - outbytes = append(outbytes, uid_bit...) - outbytes = append(outbytes, url_close...) + outbytes = append(outbytes, urlOpen...) + var urlBit = []byte(menUser.Link) + outbytes = append(outbytes, urlBit...) + outbytes = append(outbytes, bytesSinglequote...) + outbytes = append(outbytes, urlMention...) + outbytes = append(outbytes, bytesGreaterthan...) + var uidBit = []byte("@" + menUser.Name) + outbytes = append(outbytes, uidBit...) + outbytes = append(outbytes, urlClose...) lastItem = i //log.Print(string(msgbytes)) @@ -605,37 +573,37 @@ func parse_message(msg string/*, user User*/) string { //log.Print("lastItem - 1",lastItem - 1) //log.Print("msgbytes[lastItem]",msgbytes[lastItem]) //log.Print("lastItem",lastItem) - } else if msgbytes[i]=='h' || msgbytes[i]=='f' || msgbytes[i]=='g' { + } else if msgbytes[i] == 'h' || msgbytes[i] == 'f' || msgbytes[i] == 'g' { //log.Print("IN hfg") - if msgbytes[i + 1]=='t' && msgbytes[i + 2]=='t' && msgbytes[i + 3]=='p' { - if msgbytes[i + 4] == 's' && msgbytes[i + 5] == ':' && msgbytes[i + 6] == '/' && msgbytes[i + 7] == '/' { + if msgbytes[i+1] == 't' && msgbytes[i+2] == 't' && msgbytes[i+3] == 'p' { + if msgbytes[i+4] == 's' && msgbytes[i+5] == ':' && msgbytes[i+6] == '/' && msgbytes[i+7] == '/' { // Do nothing - } else if msgbytes[i + 4] == ':' && msgbytes[i + 5] == '/' && msgbytes[i + 6] == '/' { + } else if msgbytes[i+4] == ':' && msgbytes[i+5] == '/' && msgbytes[i+6] == '/' { // Do nothing } else { continue } - } else if msgbytes[i + 1] == 't' && msgbytes[i + 2] == 'p' && msgbytes[i + 3] == ':' && msgbytes[i + 4] == '/' && msgbytes[i + 5] == '/' { + } else if msgbytes[i+1] == 't' && msgbytes[i+2] == 'p' && msgbytes[i+3] == ':' && msgbytes[i+4] == '/' && msgbytes[i+5] == '/' { // Do nothing - } else if msgbytes[i + 1] == 'i' && msgbytes[i + 2] == 't' && msgbytes[i + 3] == ':' && msgbytes[i + 4] == '/' && msgbytes[i + 5] == '/' { + } else if msgbytes[i+1] == 'i' && msgbytes[i+2] == 't' && msgbytes[i+3] == ':' && msgbytes[i+4] == '/' && msgbytes[i+5] == '/' { // Do nothing } else { continue } - outbytes = append(outbytes,msgbytes[lastItem:i]...) - url_len := partial_url_bytes_len(msgbytes[i:]) - if msgbytes[i + url_len] != ' ' && msgbytes[i + url_len] != 10 { - outbytes = append(outbytes,invalid_url...) - i += url_len + outbytes = append(outbytes, msgbytes[lastItem:i]...) + urlLen := partialURLBytesLen(msgbytes[i:]) + if msgbytes[i+urlLen] != ' ' && msgbytes[i+urlLen] != 10 { + outbytes = append(outbytes, invalidURL...) + i += urlLen continue } - outbytes = append(outbytes, url_open...) - outbytes = append(outbytes, msgbytes[i:i + url_len]...) - outbytes = append(outbytes, url_open2...) - outbytes = append(outbytes, msgbytes[i:i + url_len]...) - outbytes = append(outbytes, url_close...) - i += url_len + outbytes = append(outbytes, urlOpen...) + outbytes = append(outbytes, msgbytes[i:i+urlLen]...) + outbytes = append(outbytes, urlOpen2...) + outbytes = append(outbytes, msgbytes[i:i+urlLen]...) + outbytes = append(outbytes, urlClose...) + i += urlLen lastItem = i } } @@ -660,42 +628,42 @@ func parse_message(msg string/*, user User*/) string { //log.Print(`"`+string(outbytes)+`"`) //log.Print("msg",`"`+msg+`"`) - msg = strings.Replace(msg,"\n","
",-1) + msg = strings.Replace(msg, "\n", "
", -1) if sshooks["parse_assign"] != nil { - msg = run_sshook("parse_assign", msg) + msg = runSshook("parse_assign", msg) } return msg } -func regex_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,"$2$3//$4") - msg = strings.Replace(msg,"\n","
",-1) +func regexParseMessage(msg string) string { + msg = strings.Replace(msg, ":)", "😀", -1) + msg = strings.Replace(msg, ":D", "😃", -1) + msg = strings.Replace(msg, ":P", "😛", -1) + msg = urlReg.ReplaceAllString(msg, "$2$3//$4") + msg = strings.Replace(msg, "\n", "
", -1) if sshooks["parse_assign"] != nil { - msg = run_sshook("parse_assign", msg) + msg = runSshook("parse_assign", msg) } return msg } // 6, 7, 8, 6, 7 // ftp://, http://, https:// git://, mailto: (not a URL, just here for length comparison purposes) -func validate_url_bytes(data []byte) bool { +func validateURLBytes(data []byte) bool { datalen := len(data) i := 0 if datalen >= 6 { - if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + if bytes.Equal(data[0:6], []byte("ftp://")) || bytes.Equal(data[0:6], []byte("git://")) { i = 6 - } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + } else if datalen >= 7 && bytes.Equal(data[0:7], httpProtBytes) { i = 7 - } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + } else if datalen >= 8 && bytes.Equal(data[0:8], []byte("https://")) { i = 8 } } - for ;datalen > i; i++ { + for ; datalen > i; i++ { if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { return false } @@ -703,23 +671,23 @@ func validate_url_bytes(data []byte) bool { return true } -func validated_url_bytes(data []byte) (url []byte) { +func validatedURLBytes(data []byte) (url []byte) { datalen := len(data) i := 0 if datalen >= 6 { - if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + if bytes.Equal(data[0:6], []byte("ftp://")) || bytes.Equal(data[0:6], []byte("git://")) { i = 6 - } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + } else if datalen >= 7 && bytes.Equal(data[0:7], httpProtBytes) { i = 7 - } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + } else if datalen >= 8 && bytes.Equal(data[0:8], []byte("https://")) { i = 8 } } - for ;datalen > i; i++ { + for ; datalen > i; i++ { if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { - return invalid_url + return invalidURL } } @@ -727,22 +695,22 @@ func validated_url_bytes(data []byte) (url []byte) { return url } -func partial_url_bytes(data []byte) (url []byte) { +func partialURLBytes(data []byte) (url []byte) { datalen := len(data) i := 0 end := datalen - 1 if datalen >= 6 { - if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + if bytes.Equal(data[0:6], []byte("ftp://")) || bytes.Equal(data[0:6], []byte("git://")) { i = 6 - } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + } else if datalen >= 7 && bytes.Equal(data[0:7], httpProtBytes) { i = 7 - } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + } else if datalen >= 8 && bytes.Equal(data[0:8], []byte("https://")) { i = 8 } } - for ;end >= i; i++ { + for ; end >= i; i++ { if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { end = i } @@ -752,22 +720,22 @@ func partial_url_bytes(data []byte) (url []byte) { return url } -func partial_url_bytes_len(data []byte) int { +func partialURLBytesLen(data []byte) int { datalen := len(data) i := 0 if datalen >= 6 { //log.Print(string(data[0:5])) - if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + if bytes.Equal(data[0:6], []byte("ftp://")) || bytes.Equal(data[0:6], []byte("git://")) { i = 6 - } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + } else if datalen >= 7 && bytes.Equal(data[0:7], httpProtBytes) { i = 7 - } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + } else if datalen >= 8 && bytes.Equal(data[0:8], []byte("https://")) { i = 8 } } - for ;datalen > i; i++ { + for ; datalen > i; i++ { if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { //log.Print("Bad Character:",data[i]) return i @@ -778,26 +746,26 @@ func partial_url_bytes_len(data []byte) int { return datalen } -func parse_media_bytes(data []byte) (protocol []byte, url []byte) { +func parseMediaBytes(data []byte) (protocol []byte, url []byte) { datalen := len(data) i := 0 if datalen >= 6 { - if bytes.Equal(data[0:6],[]byte("ftp://")) || bytes.Equal(data[0:6],[]byte("git://")) { + if bytes.Equal(data[0:6], []byte("ftp://")) || bytes.Equal(data[0:6], []byte("git://")) { i = 6 protocol = data[0:2] - } else if datalen >= 7 && bytes.Equal(data[0:7],http_prot_b) { + } else if datalen >= 7 && bytes.Equal(data[0:7], httpProtBytes) { i = 7 protocol = []byte("http") - } else if datalen >= 8 && bytes.Equal(data[0:8],[]byte("https://")) { + } else if datalen >= 8 && bytes.Equal(data[0:8], []byte("https://")) { i = 8 protocol = []byte("https") } } - for ;datalen > i; i++ { + for ; datalen > i; i++ { if data[i] != '\\' && data[i] != '_' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) { - return []byte(""), invalid_url + return []byte(""), invalidURL } } @@ -807,13 +775,13 @@ func parse_media_bytes(data []byte) (protocol []byte, url []byte) { return protocol, data[i:] } -func coerce_int_bytes(data []byte) (res int, length int) { +func coerceIntBytes(data []byte) (res int, length int) { if !(data[0] > 47 && data[0] < 58) { return 0, 1 } i := 0 - for ;len(data) > i; i++ { + for ; len(data) > i; i++ { if !(data[i] > 47 && data[i] < 58) { conv, err := strconv.Atoi(string(data[0:i])) if err != nil { @@ -831,16 +799,15 @@ func coerce_int_bytes(data []byte) (res int, length int) { } // TO-DO: Write tests for this -func paginate(count int, per_page int, maxPages int) []int { - if count < per_page { +func paginate(count int, perPage int, maxPages int) []int { + if count < perPage { return []int{1} } - var page int var out []int - for current := 0; current < count; current += per_page { + for current := 0; current < count; current += perPage { page++ - out = append(out,page) + out = append(out, page) if len(out) >= maxPages { break } @@ -849,9 +816,9 @@ func paginate(count int, per_page int, maxPages int) []int { } // TO-DO: Write tests for this -func page_offset(count int, page int, perPage int) (int, int, int) { +func pageOffset(count int, page int, perPage int) (int, int, int) { var offset int - lastPage := int(count / perPage) + 1 + lastPage := (count / perPage) + 1 if page > 1 { offset = (perPage * page) - perPage } else if page == -1 { diff --git a/panel_routes.go b/panel_routes.go index 967357c1..5c2f2889 100644 --- a/panel_routes.go +++ b/panel_routes.go @@ -1,27 +1,27 @@ package main import ( - "log" - "fmt" - "errors" - "strings" - "strconv" - "html" "encoding/json" - "net/http" + "errors" + "fmt" + "html" "html/template" + "log" + "net/http" + "strconv" + "strings" "github.com/Azareal/gopsutil/mem" ) -func route_panel(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } // We won't calculate this on the spot anymore, as the system doesn't seem to like it if we do multiple fetches simultaneously. Should we constantly calculate this on a background thread? Perhaps, the watchdog to scale back heavy features under load? One plus side is that we'd get immediate CPU percentages here instead of waiting it to kick in with WebSockets - var cpustr string = "Unknown" + var cpustr = "Unknown" var cpuColour string var ramstr, ramColour string @@ -29,24 +29,24 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){ if err != nil { ramstr = "Unknown" } else { - total_count, total_unit := convert_byte_unit(float64(memres.Total)) - used_count := convert_byte_in_unit(float64(memres.Total - memres.Available),total_unit) + totalCount, totalUnit := convertByteUnit(float64(memres.Total)) + usedCount := convertByteInUnit(float64(memres.Total-memres.Available), totalUnit) // Round totals with .9s up, it's how most people see it anyway. Floats are notoriously imprecise, so do it off 0.85 //log.Print("pre used_count",used_count) var totstr string - if (total_count - float64(int(total_count))) > 0.85 { - used_count += 1.0 - (total_count - float64(int(total_count))) - totstr = strconv.Itoa(int(total_count) + 1) + if (totalCount - float64(int(totalCount))) > 0.85 { + usedCount += 1.0 - (totalCount - float64(int(totalCount))) + totstr = strconv.Itoa(int(totalCount) + 1) } else { - totstr = fmt.Sprintf("%.1f",total_count) + totstr = fmt.Sprintf("%.1f", totalCount) } //log.Print("post used_count",used_count) - if used_count > total_count { - used_count = total_count + if usedCount > totalCount { + usedCount = totalCount } - ramstr = fmt.Sprintf("%.1f",used_count) + " / " + totstr + total_unit + ramstr = fmt.Sprintf("%.1f", usedCount) + " / " + totstr + totalUnit ramperc := ((memres.Total - memres.Available) * 100) / memres.Total //log.Print("ramperc",ramperc) @@ -62,10 +62,10 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){ var postCount int err = todays_post_count_stmt.QueryRow().Scan(&postCount) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } - var postInterval string = "day" + var postInterval = "day" var postColour string if postCount > 25 { @@ -79,10 +79,10 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){ var topicCount int err = todays_topic_count_stmt.QueryRow().Scan(&topicCount) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } - var topicInterval string = "day" + var topicInterval = "day" var topicColour string if topicCount > 8 { @@ -96,28 +96,28 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){ var reportCount int err = todays_report_count_stmt.QueryRow().Scan(&reportCount) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } - var reportInterval string = "week" + var reportInterval = "week" var newUserCount int err = todays_newuser_count_stmt.QueryRow().Scan(&newUserCount) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } - var newUserInterval string = "week" + var newUserInterval = "week" - var gridElements []GridElement = []GridElement{ - GridElement{"dash-version","v" + version.String(),0,"grid_istat stat_green","","","Gosora is up-to-date :)"}, - GridElement{"dash-cpu","CPU: " + cpustr,1,"grid_istat " + cpuColour,"","","The global CPU usage of this server"}, - GridElement{"dash-ram","RAM: " + ramstr,2,"grid_istat " + ramColour,"","","The global RAM usage of this server"}, + var gridElements = []GridElement{ + GridElement{"dash-version", "v" + version.String(), 0, "grid_istat stat_green", "", "", "Gosora is up-to-date :)"}, + GridElement{"dash-cpu", "CPU: " + cpustr, 1, "grid_istat " + cpuColour, "", "", "The global CPU usage of this server"}, + GridElement{"dash-ram", "RAM: " + ramstr, 2, "grid_istat " + ramColour, "", "", "The global RAM usage of this server"}, } - if enable_websockets { - uonline := ws_hub.user_count() - gonline := ws_hub.guest_count() + if enableWebsockets { + uonline := wsHub.userCount() + gonline := wsHub.guestCount() totonline := uonline + gonline var onlineColour string @@ -147,210 +147,210 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){ onlineUsersColour = "stat_red" } - totonline, totunit := convert_friendly_unit(totonline) - uonline, uunit := convert_friendly_unit(uonline) - gonline, gunit := convert_friendly_unit(gonline) + totonline, totunit := convertFriendlyUnit(totonline) + uonline, uunit := convertFriendlyUnit(uonline) + gonline, gunit := convertFriendlyUnit(gonline) - gridElements = append(gridElements, GridElement{"dash-totonline",strconv.Itoa(totonline) + totunit + " online",3,"grid_stat " + onlineColour,"","","The number of people who are currently online"}) - gridElements = append(gridElements, GridElement{"dash-gonline",strconv.Itoa(gonline) + gunit + " guests online",4,"grid_stat " + onlineGuestsColour,"","","The number of guests who are currently online"}) - gridElements = append(gridElements, GridElement{"dash-uonline",strconv.Itoa(uonline) + uunit + " users online",5,"grid_stat " + onlineUsersColour,"","","The number of logged-in users who are currently online"}) + gridElements = append(gridElements, GridElement{"dash-totonline", strconv.Itoa(totonline) + totunit + " online", 3, "grid_stat " + onlineColour, "", "", "The number of people who are currently online"}) + gridElements = append(gridElements, GridElement{"dash-gonline", strconv.Itoa(gonline) + gunit + " guests online", 4, "grid_stat " + onlineGuestsColour, "", "", "The number of guests who are currently online"}) + gridElements = append(gridElements, GridElement{"dash-uonline", strconv.Itoa(uonline) + uunit + " users online", 5, "grid_stat " + onlineUsersColour, "", "", "The number of logged-in users who are currently online"}) } - gridElements = append(gridElements, GridElement{"dash-postsperday",strconv.Itoa(postCount) + " posts / " + postInterval,6,"grid_stat " + postColour,"","","The number of new posts over the last 24 hours"}) - gridElements = append(gridElements, GridElement{"dash-topicsperday",strconv.Itoa(topicCount) + " topics / " + topicInterval,7,"grid_stat " + topicColour,"","","The number of new topics over the last 24 hours"}) - gridElements = append(gridElements, GridElement{"dash-totonlineperday","20 online / day",8,"grid_stat stat_disabled","","","Coming Soon!"/*"The people online over the last 24 hours"*/}) + gridElements = append(gridElements, GridElement{"dash-postsperday", strconv.Itoa(postCount) + " posts / " + postInterval, 6, "grid_stat " + postColour, "", "", "The number of new posts over the last 24 hours"}) + gridElements = append(gridElements, GridElement{"dash-topicsperday", strconv.Itoa(topicCount) + " topics / " + topicInterval, 7, "grid_stat " + topicColour, "", "", "The number of new topics over the last 24 hours"}) + gridElements = append(gridElements, GridElement{"dash-totonlineperday", "20 online / day", 8, "grid_stat stat_disabled", "", "", "Coming Soon!" /*"The people online over the last 24 hours"*/}) - gridElements = append(gridElements, GridElement{"dash-searches","8 searches / week",9,"grid_stat stat_disabled","","","Coming Soon!"/*"The number of searches over the last 7 days"*/}) - gridElements = append(gridElements, GridElement{"dash-newusers",strconv.Itoa(newUserCount) + " new users / " + newUserInterval,10,"grid_stat","","","The number of new users over the last 7 days"}) - gridElements = append(gridElements, GridElement{"dash-reports",strconv.Itoa(reportCount) + " reports / " + reportInterval,11,"grid_stat","","","The number of reports over the last 7 days"}) + gridElements = append(gridElements, GridElement{"dash-searches", "8 searches / week", 9, "grid_stat stat_disabled", "", "", "Coming Soon!" /*"The number of searches over the last 7 days"*/}) + gridElements = append(gridElements, GridElement{"dash-newusers", strconv.Itoa(newUserCount) + " new users / " + newUserInterval, 10, "grid_stat", "", "", "The number of new users over the last 7 days"}) + gridElements = append(gridElements, GridElement{"dash-reports", strconv.Itoa(reportCount) + " reports / " + reportInterval, 11, "grid_stat", "", "", "The number of reports over the last 7 days"}) - gridElements = append(gridElements, GridElement{"dash-minperuser","2 minutes / user / week",12,"grid_stat stat_disabled","","","Coming Soon!"/*"The average number of number of minutes spent by each active user over the last 7 days"*/}) - gridElements = append(gridElements, GridElement{"dash-visitorsperweek","2 visitors / week",13,"grid_stat stat_disabled","","","Coming Soon!"/*"The number of unique visitors we've had over the last 7 days"*/}) - gridElements = append(gridElements, GridElement{"dash-postsperuser","5 posts / user / week",14,"grid_stat stat_disabled","","","Coming Soon!"/*"The average number of posts made by each active user over the past week"*/}) + gridElements = append(gridElements, GridElement{"dash-minperuser", "2 minutes / user / week", 12, "grid_stat stat_disabled", "", "", "Coming Soon!" /*"The average number of number of minutes spent by each active user over the last 7 days"*/}) + gridElements = append(gridElements, GridElement{"dash-visitorsperweek", "2 visitors / week", 13, "grid_stat stat_disabled", "", "", "Coming Soon!" /*"The number of unique visitors we've had over the last 7 days"*/}) + gridElements = append(gridElements, GridElement{"dash-postsperuser", "5 posts / user / week", 14, "grid_stat stat_disabled", "", "", "Coming Soon!" /*"The average number of posts made by each active user over the past week"*/}) - pi := PanelDashboardPage{"Control Panel Dashboard",user,headerVars,stats,gridElements,extData} - if pre_render_hooks["pre_render_panel_dashboard"] != nil { - if run_pre_render_hook("pre_render_panel_dashboard", w, r, &user, &pi) { + pi := PanelDashboardPage{"Control Panel Dashboard", user, headerVars, stats, gridElements} + if preRenderHooks["pre_render_panel_dashboard"] != nil { + if runPreRenderHook("pre_render_panel_dashboard", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-dashboard.html",pi) + err = templates.ExecuteTemplate(w, "panel-dashboard.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_forums(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_forums(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageForums { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } var forumList []interface{} forums, err := fstore.GetAll() if err != nil { - InternalError(err,w) + InternalError(err, w) return } for _, forum := range forums { if forum.Name != "" && forum.ParentID == 0 { - fadmin := ForumAdmin{forum.ID,forum.Name,forum.Desc,forum.Active,forum.Preset,forum.TopicCount,preset_to_lang(forum.Preset)} + fadmin := ForumAdmin{forum.ID, forum.Name, forum.Desc, forum.Active, forum.Preset, forum.TopicCount, presetToLang(forum.Preset)} if fadmin.Preset == "" { fadmin.Preset = "custom" } - forumList = append(forumList,fadmin) + forumList = append(forumList, fadmin) } } - pi := PanelPage{"Forum Manager",user,headerVars,stats,forumList,nil} - if pre_render_hooks["pre_render_panel_forums"] != nil { - if run_pre_render_hook("pre_render_panel_forums", w, r, &user, &pi) { + pi := PanelPage{"Forum Manager", user, headerVars, stats, forumList, nil} + if preRenderHooks["pre_render_panel_forums"] != nil { + if runPreRenderHook("pre_render_panel_forums", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-forums.html",pi) + err = templates.ExecuteTemplate(w, "panel-forums.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request, user User){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request, user User) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageForums { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } fname := r.PostFormValue("forum-name") fdesc := r.PostFormValue("forum-desc") - fpreset := strip_invalid_preset(r.PostFormValue("forum-preset")) + fpreset := stripInvalidPreset(r.PostFormValue("forum-preset")) factive := r.PostFormValue("forum-name") - active := (factive == "on" || factive == "1" ) + active := (factive == "on" || factive == "1") - _, err = fstore.CreateForum(fname,fdesc,active,fpreset) + _, err = fstore.CreateForum(fname, fdesc, active, fpreset) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/forums/", http.StatusSeeOther) } -func route_panel_forums_delete(w http.ResponseWriter, r *http.Request, user User, sfid string){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_forums_delete(w http.ResponseWriter, r *http.Request, user User, sfid string) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageForums { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } fid, err := strconv.Atoi(sfid) if err != nil { - LocalError("The provided Forum ID is not a valid number.",w,r,user) + LocalError("The provided Forum ID is not a valid number.", w, r, user) return } forum, err := fstore.CascadeGet(fid) if err == ErrNoRows { - LocalError("The forum you're trying to delete doesn't exist.",w,r,user) + LocalError("The forum you're trying to delete doesn't exist.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } confirm_msg := "Are you sure you want to delete the '" + forum.Name + "' forum?" - yousure := AreYouSure{"/panel/forums/delete/submit/" + strconv.Itoa(fid),confirm_msg} + yousure := AreYouSure{"/panel/forums/delete/submit/" + strconv.Itoa(fid), confirm_msg} - pi := PanelPage{"Delete Forum",user,headerVars,stats,tList,yousure} - if pre_render_hooks["pre_render_panel_delete_forum"] != nil { - if run_pre_render_hook("pre_render_panel_delete_forum", w, r, &user, &pi) { + pi := PanelPage{"Delete Forum", user, headerVars, stats, tList, yousure} + if preRenderHooks["pre_render_panel_delete_forum"] != nil { + if runPreRenderHook("pre_render_panel_delete_forum", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"areyousure.html",pi) + err = templates.ExecuteTemplate(w, "areyousure.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request, user User, sfid string) { - _, ok := SimplePanelSessionCheck(w,r,&user) + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageForums { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } fid, err := strconv.Atoi(sfid) if err != nil { - LocalError("The provided Forum ID is not a valid number.",w,r,user) + LocalError("The provided Forum ID is not a valid number.", w, r, user) return } err = fstore.CascadeDelete(fid) if err == ErrNoRows { - LocalError("The forum you're trying to delete doesn't exist.",w,r,user) + LocalError("The forum you're trying to delete doesn't exist.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/forums/", http.StatusSeeOther) } func route_panel_forums_edit(w http.ResponseWriter, r *http.Request, user User, sfid string) { - headerVars, stats, ok := PanelSessionCheck(w,r,&user) + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageForums { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } fid, err := strconv.Atoi(sfid) if err != nil { - LocalError("The provided Forum ID is not a valid number.",w,r,user) + LocalError("The provided Forum ID is not a valid number.", w, r, user) return } forum, err := fstore.CascadeGet(fid) if err == ErrNoRows { - LocalError("The forum you're trying to edit doesn't exist.",w,r,user) + LocalError("The forum you're trying to edit doesn't exist.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -358,68 +358,65 @@ func route_panel_forums_edit(w http.ResponseWriter, r *http.Request, user User, forum.Preset = "custom" } - var glist []Group = groups + var glist = groups var gplist []GroupForumPermPreset for gid, group := range glist { if gid == 0 { continue } - gplist = append(gplist,GroupForumPermPreset{group,forum_perms_to_group_forum_preset(group.Forums[fid])}) + gplist = append(gplist, GroupForumPermPreset{group, forumPermsToGroupForumPreset(group.Forums[fid])}) } - pi := PanelEditForumPage{"Forum Editor",user,headerVars,stats,forum.ID,forum.Name,forum.Desc,forum.Active,forum.Preset,gplist,extData} - if pre_render_hooks["pre_render_panel_edit_forum"] != nil { - if run_pre_render_hook("pre_render_panel_edit_forum", w, r, &user, &pi) { + pi := PanelEditForumPage{"Forum Editor", user, headerVars, stats, forum.ID, forum.Name, forum.Desc, forum.Active, forum.Preset, gplist} + if preRenderHooks["pre_render_panel_edit_forum"] != nil { + if runPreRenderHook("pre_render_panel_edit_forum", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-forum-edit.html",pi) + err = templates.ExecuteTemplate(w, "panel-forum-edit.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request, user User, sfid string) { - _, ok := SimplePanelSessionCheck(w,r,&user) + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageForums { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } - is_js := r.PostFormValue("js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("js") == "1") fid, err := strconv.Atoi(sfid) if err != nil { - LocalErrorJSQ("The provided Forum ID is not a valid number.",w,r,user,is_js) + LocalErrorJSQ("The provided Forum ID is not a valid number.", w, r, user, isJs) return } forum_name := r.PostFormValue("forum_name") forum_desc := r.PostFormValue("forum_desc") - forum_preset := strip_invalid_preset(r.PostFormValue("forum_preset")) + forum_preset := stripInvalidPreset(r.PostFormValue("forum_preset")) forum_active := r.PostFormValue("forum_active") forum, err := fstore.CascadeGet(fid) if err == ErrNoRows { - LocalErrorJSQ("The forum you're trying to edit doesn't exist.",w,r,user,is_js) + LocalErrorJSQ("The forum you're trying to edit doesn't exist.", w, r, user, isJs) return } else if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } @@ -436,10 +433,10 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request, user active = false } - forum_update_mutex.Lock() - _, err = update_forum_stmt.Exec(forum_name,forum_desc,active,forum_preset,fid) + forumUpdateMutex.Lock() + _, err = update_forum_stmt.Exec(forum_name, forum_desc, active, forum_preset, fid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } if forum.Name != forum_name { @@ -454,106 +451,103 @@ func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request, user if forum.Preset != forum_preset { forum.Preset = forum_preset } - forum_update_mutex.Unlock() + forumUpdateMutex.Unlock() - permmap_to_query(preset_to_permmap(forum_preset),fid) + permmapToQuery(presetToPermmap(forum_preset), fid) - if is_js == "0" { - http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther) + if !isJs { + http.Redirect(w, r, "/panel/forums/", http.StatusSeeOther) } else { - w.Write(success_json_bytes) + w.Write(successJSONBytes) } } -func route_panel_forums_edit_perms_submit(w http.ResponseWriter, r *http.Request, user User, sfid string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_forums_edit_perms_submit(w http.ResponseWriter, r *http.Request, user User, sfid string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageForums { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } - is_js := r.PostFormValue("js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("js") == "1") fid, err := strconv.Atoi(sfid) if err != nil { - LocalErrorJSQ("The provided Forum ID is not a valid number.",w,r,user,is_js) + LocalErrorJSQ("The provided Forum ID is not a valid number.", w, r, user, isJs) return } gid, err := strconv.Atoi(r.PostFormValue("gid")) if err != nil { - LocalErrorJSQ("Invalid Group ID",w,r,user,is_js) + LocalErrorJSQ("Invalid Group ID", w, r, user, isJs) return } - perm_preset := strip_invalid_group_forum_preset(r.PostFormValue("perm_preset")) - fperms, changed := group_forum_preset_to_forum_perms(perm_preset) + perm_preset := stripInvalidGroupForumPreset(r.PostFormValue("perm_preset")) + fperms, changed := groupForumPresetToForumPerms(perm_preset) forum, err := fstore.CascadeGet(fid) if err == ErrNoRows { - LocalErrorJSQ("This forum doesn't exist",w,r,user,is_js) + LocalErrorJSQ("This forum doesn't exist", w, r, user, isJs) return } else if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - forum_update_mutex.Lock() - defer forum_update_mutex.Unlock() + forumUpdateMutex.Lock() + defer forumUpdateMutex.Unlock() if changed { - permupdate_mutex.Lock() + permUpdateMutex.Lock() groups[gid].Forums[fid] = fperms perms, err := json.Marshal(fperms) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - _, err = add_forum_perms_to_group_stmt.Exec(gid,fid,perm_preset,perms) + _, err = add_forum_perms_to_group_stmt.Exec(gid, fid, perm_preset, perms) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - permupdate_mutex.Unlock() + permUpdateMutex.Unlock() - _, err = update_forum_stmt.Exec(forum.Name,forum.Desc,forum.Active,"",fid) + _, err = update_forum_stmt.Exec(forum.Name, forum.Desc, forum.Active, "", fid) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } forum.Preset = "" } - if is_js == "0" { - http.Redirect(w,r,"/panel/forums/edit/" + strconv.Itoa(fid),http.StatusSeeOther) + if !isJs { + http.Redirect(w, r, "/panel/forums/edit/"+strconv.Itoa(fid), http.StatusSeeOther) } else { - w.Write(success_json_bytes) + w.Write(successJSONBytes) } } -func route_panel_settings(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_settings(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditSettings { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } @@ -561,28 +555,29 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request, user User){ var settingList map[string]interface{} = make(map[string]interface{}) rows, err := get_settings_stmt.Query() if err != nil { - InternalError(err,w) + InternalError(err, w) return } defer rows.Close() + var settingLabels map[string]string = GetAllSettingLabels() var sname, scontent, stype string for rows.Next() { - err := rows.Scan(&sname,&scontent,&stype) + err := rows.Scan(&sname, &scontent, &stype) if err != nil { - InternalError(err,w) + InternalError(err, w) return } if stype == "list" { llist := settingLabels[sname] - labels := strings.Split(llist,",") + labels := strings.Split(llist, ",") conv, err := strconv.Atoi(scontent) if err != nil { - LocalError("The setting '" + sname + "' can't be converted to an integer",w,r,user) + LocalError("The setting '"+sname+"' can't be converted to an integer", w, r, user) return } - scontent = labels[conv - 1] + scontent = labels[conv-1] } else if stype == "bool" { if scontent == "1" { scontent = "Yes" @@ -594,95 +589,90 @@ func route_panel_settings(w http.ResponseWriter, r *http.Request, user User){ } err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) return } - pi := PanelPage{"Setting Manager",user,headerVars,stats,tList,settingList} - if pre_render_hooks["pre_render_panel_settings"] != nil { - if run_pre_render_hook("pre_render_panel_settings", w, r, &user, &pi) { + pi := PanelPage{"Setting Manager", user, headerVars, stats, tList, settingList} + if preRenderHooks["pre_render_panel_settings"] != nil { + if runPreRenderHook("pre_render_panel_settings", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-settings.html",pi) + err = templates.ExecuteTemplate(w, "panel-settings.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_setting(w http.ResponseWriter, r *http.Request, user User, sname string){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_setting(w http.ResponseWriter, r *http.Request, user User, sname string) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditSettings { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } - setting := Setting{sname,"","",""} + setting := Setting{sname, "", "", ""} - err := get_setting_stmt.QueryRow(setting.Name).Scan(&setting.Content,&setting.Type) + err := get_setting_stmt.QueryRow(setting.Name).Scan(&setting.Content, &setting.Type) if err == ErrNoRows { - LocalError("The setting you want to edit doesn't exist.",w,r,user) + LocalError("The setting you want to edit doesn't exist.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } var itemList []interface{} if setting.Type == "list" { - llist, ok := settingLabels[setting.Name] - if !ok { - LocalError("The labels for this setting don't exist",w,r,user) - return - } - + llist := GetSettingLabel(setting.Name) conv, err := strconv.Atoi(setting.Content) if err != nil { - LocalError("The value of this setting couldn't be converted to an integer",w,r,user) + LocalError("The value of this setting couldn't be converted to an integer", w, r, user) return } - labels := strings.Split(llist,",") + labels := strings.Split(llist, ",") for index, label := range labels { itemList = append(itemList, OptionLabel{ - Label: label, - Value: index + 1, + Label: label, + Value: index + 1, Selected: conv == (index + 1), }) } } - pi := PanelPage{"Edit Setting",user,headerVars,stats,itemList,setting} - if pre_render_hooks["pre_render_panel_setting"] != nil { - if run_pre_render_hook("pre_render_panel_setting", w, r, &user, &pi) { + pi := PanelPage{"Edit Setting", user, headerVars, stats, itemList, setting} + if preRenderHooks["pre_render_panel_setting"] != nil { + if runPreRenderHook("pre_render_panel_setting", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-setting.html",pi) + err = templates.ExecuteTemplate(w, "panel-setting.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } func route_panel_setting_edit(w http.ResponseWriter, r *http.Request, user User, sname string) { - headerLite, ok := SimplePanelSessionCheck(w,r,&user) + headerLite, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditSettings { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } @@ -691,10 +681,10 @@ func route_panel_setting_edit(w http.ResponseWriter, r *http.Request, user User, err = get_full_setting_stmt.QueryRow(sname).Scan(&sname, &stype, &sconstraints) if err == ErrNoRows { - LocalError("The setting you want to edit doesn't exist.",w,r,user) + LocalError("The setting you want to edit doesn't exist.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -706,207 +696,199 @@ func route_panel_setting_edit(w http.ResponseWriter, r *http.Request, user User, } } - _, err = update_setting_stmt.Exec(scontent,sname) + _, err = update_setting_stmt.Exec(scontent, sname) if err != nil { - InternalError(err,w) + InternalError(err, w) return } errmsg := headerLite.Settings.ParseSetting(sname, scontent, stype, sconstraints) if errmsg != "" { - LocalError(errmsg,w,r,user) + LocalError(errmsg, w, r, user) return } settingBox.Store(headerLite.Settings) - http.Redirect(w,r,"/panel/settings/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/settings/", http.StatusSeeOther) } -func route_panel_word_filters(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_word_filters(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditSettings { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } var filterList WordFilterBox = wordFilterBox.Load().(WordFilterBox) - pi := PanelPage{"Word Filter Manager",user,headerVars,stats,tList,filterList} - if pre_render_hooks["pre_render_panel_word_filters"] != nil { - if run_pre_render_hook("pre_render_panel_word_filters", w, r, &user, &pi) { + pi := PanelPage{"Word Filter Manager", user, headerVars, stats, tList, filterList} + if preRenderHooks["pre_render_panel_word_filters"] != nil { + if runPreRenderHook("pre_render_panel_word_filters", w, r, &user, &pi) { return } } - err := templates.ExecuteTemplate(w,"panel-word-filters.html",pi) + err := templates.ExecuteTemplate(w, "panel-word-filters.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_word_filters_create(w http.ResponseWriter, r *http.Request, user User){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_word_filters_create(w http.ResponseWriter, r *http.Request, user User) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditSettings { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } - is_js := r.PostFormValue("js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("js") == "1") find := strings.TrimSpace(r.PostFormValue("find")) if find == "" { - LocalErrorJSQ("You need to specify what word you want to match",w,r,user,is_js) + LocalErrorJSQ("You need to specify what word you want to match", w, r, user, isJs) return } // Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement replacement := strings.TrimSpace(r.PostFormValue("replacement")) - res, err := create_word_filter_stmt.Exec(find,replacement) + res, err := create_word_filter_stmt.Exec(find, replacement) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } lastId, err := res.LastInsertId() if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } - add_word_filter(int(lastId),find,replacement) - http.Redirect(w,r,"/panel/settings/word-filters/",http.StatusSeeOther) + addWordFilter(int(lastId), find, replacement) + http.Redirect(w, r, "/panel/settings/word-filters/", http.StatusSeeOther) // TO-DO: Return json for JS? } -func route_panel_word_filters_edit(w http.ResponseWriter, r *http.Request, user User, wfid string){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_word_filters_edit(w http.ResponseWriter, r *http.Request, user User, wfid string) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditSettings { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } _ = wfid - pi := PanelPage{"Edit Word Filter",user,headerVars,stats,tList,nil} - if pre_render_hooks["pre_render_panel_word_filters_edit"] != nil { - if run_pre_render_hook("pre_render_panel_word_filters_edit", w, r, &user, &pi) { + pi := PanelPage{"Edit Word Filter", user, headerVars, stats, tList, nil} + if preRenderHooks["pre_render_panel_word_filters_edit"] != nil { + if runPreRenderHook("pre_render_panel_word_filters_edit", w, r, &user, &pi) { return } } - err := templates.ExecuteTemplate(w,"panel-word-filters-edit.html",pi) + err := templates.ExecuteTemplate(w, "panel-word-filters-edit.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_word_filters_edit_submit(w http.ResponseWriter, r *http.Request, user User, wfid string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_word_filters_edit_submit(w http.ResponseWriter, r *http.Request, user User, wfid string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } - is_js := r.PostFormValue("is_js") - if is_js == "" { - is_js = "0" - } + // TO-DO: Either call it isJs or js rather than flip-flopping back and forth across the routes x.x + isJs := (r.PostFormValue("isJs") == "1") if !user.Perms.EditSettings { - NoPermissionsJSQ(w,r,user,is_js) + NoPermissionsJSQ(w, r, user, isJs) return } id, err := strconv.Atoi(wfid) if err != nil { - LocalErrorJSQ("The word filter ID must be an integer.",w,r,user,is_js) + LocalErrorJSQ("The word filter ID must be an integer.", w, r, user, isJs) return } find := strings.TrimSpace(r.PostFormValue("find")) if find == "" { - LocalErrorJSQ("You need to specify what word you want to match",w,r,user,is_js) + LocalErrorJSQ("You need to specify what word you want to match", w, r, user, isJs) return } // Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement replacement := strings.TrimSpace(r.PostFormValue("replacement")) - _, err = update_word_filter_stmt.Exec(find,replacement,id) + _, err = update_word_filter_stmt.Exec(find, replacement, id) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } wordFilters := wordFilterBox.Load().(WordFilterBox) - wordFilters[id] = WordFilter{ID:id,Find:find,Replacement:replacement} + wordFilters[id] = WordFilter{ID: id, Find: find, Replacement: replacement} wordFilterBox.Store(wordFilters) - http.Redirect(w,r,"/panel/settings/word-filters/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/settings/word-filters/", http.StatusSeeOther) } -func route_panel_word_filters_delete_submit(w http.ResponseWriter, r *http.Request, user User, wfid string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_word_filters_delete_submit(w http.ResponseWriter, r *http.Request, user User, wfid string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } - is_js := r.PostFormValue("is_js") - if is_js == "" { - is_js = "0" - } + isJs := (r.PostFormValue("isJs") == "1") if !user.Perms.EditSettings { - NoPermissionsJSQ(w,r,user,is_js) + NoPermissionsJSQ(w, r, user, isJs) return } id, err := strconv.Atoi(wfid) if err != nil { - LocalErrorJSQ("The word filter ID must be an integer.",w,r,user,is_js) + LocalErrorJSQ("The word filter ID must be an integer.", w, r, user, isJs) return } _, err = delete_word_filter_stmt.Exec(id) if err != nil { - InternalErrorJSQ(err,w,r,is_js) + InternalErrorJSQ(err, w, r, isJs) return } wordFilters := wordFilterBox.Load().(WordFilterBox) - delete(wordFilters,id) + delete(wordFilters, id) wordFilterBox.Store(wordFilters) - http.Redirect(w,r,"/panel/settings/word-filters/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/settings/word-filters/", http.StatusSeeOther) } -func route_panel_plugins(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_plugins(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManagePlugins { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } @@ -914,51 +896,51 @@ func route_panel_plugins(w http.ResponseWriter, r *http.Request, user User){ for _, plugin := range plugins { //log.Print("plugin.Name",plugin.Name) //log.Print("plugin.Installed",plugin.Installed) - pluginList = append(pluginList,plugin) + pluginList = append(pluginList, plugin) } - pi := PanelPage{"Plugin Manager",user,headerVars,stats,pluginList,nil} - if pre_render_hooks["pre_render_panel_plugins"] != nil { - if run_pre_render_hook("pre_render_panel_plugins", w, r, &user, &pi) { + pi := PanelPage{"Plugin Manager", user, headerVars, stats, pluginList, nil} + if preRenderHooks["pre_render_panel_plugins"] != nil { + if runPreRenderHook("pre_render_panel_plugins", w, r, &user, &pi) { return } } - err := templates.ExecuteTemplate(w,"panel-plugins.html",pi) + err := templates.ExecuteTemplate(w, "panel-plugins.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request, user User, uname string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request, user User, uname string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManagePlugins { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } //log.Print("uname","'"+uname+"'") plugin, ok := plugins[uname] if !ok { - LocalError("The plugin isn't registered in the system",w,r,user) + LocalError("The plugin isn't registered in the system", w, r, user) return } if plugin.Installable && !plugin.Installed { - LocalError("You can't activate this plugin without installing it first",w,r,user) + LocalError("You can't activate this plugin without installing it first", w, r, user) return } var active bool err := is_plugin_active_stmt.QueryRow(uname).Scan(&active) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } var has_plugin bool = (err == nil) @@ -966,7 +948,7 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request, user U if plugins[uname].Activate != nil { err = plugins[uname].Activate() if err != nil { - LocalError(err.Error(),w,r,user) + LocalError(err.Error(), w, r, user) return } } @@ -975,20 +957,20 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request, user U //log.Print("active",active) if has_plugin { if active { - LocalError("The plugin is already active",w,r,user) + LocalError("The plugin is already active", w, r, user) return } //log.Print("update_plugin") - _, err = update_plugin_stmt.Exec(1,uname) + _, err = update_plugin_stmt.Exec(1, uname) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } else { //log.Print("add_plugin") - _, err := add_plugin_stmt.Exec(uname,1,0) + _, err := add_plugin_stmt.Exec(uname, 1, 0) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } @@ -998,51 +980,51 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request, user U plugins[uname] = plugin err = plugins[uname].Init() if err != nil { - LocalError(err.Error(),w,r,user) + LocalError(err.Error(), w, r, user) return } - http.Redirect(w,r,"/panel/plugins/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther) } -func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request, user User, uname string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request, user User, uname string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManagePlugins { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } plugin, ok := plugins[uname] if !ok { - LocalError("The plugin isn't registered in the system",w,r,user) + LocalError("The plugin isn't registered in the system", w, r, user) return } var active bool err := is_plugin_active_stmt.QueryRow(uname).Scan(&active) if err == ErrNoRows { - LocalError("The plugin you're trying to deactivate isn't active",w,r,user) + LocalError("The plugin you're trying to deactivate isn't active", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } if !active { - LocalError("The plugin you're trying to deactivate isn't active",w,r,user) + LocalError("The plugin you're trying to deactivate isn't active", w, r, user) return } - _, err = update_plugin_stmt.Exec(0,uname) + _, err = update_plugin_stmt.Exec(0, uname) if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -1050,43 +1032,43 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request, user plugins[uname] = plugin plugins[uname].Deactivate() - http.Redirect(w,r,"/panel/plugins/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther) } -func route_panel_plugins_install(w http.ResponseWriter, r *http.Request, user User, uname string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_plugins_install(w http.ResponseWriter, r *http.Request, user User, uname string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManagePlugins { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } plugin, ok := plugins[uname] if !ok { - LocalError("The plugin isn't registered in the system",w,r,user) + LocalError("The plugin isn't registered in the system", w, r, user) return } if !plugin.Installable { - LocalError("This plugin is not installable",w,r,user) + LocalError("This plugin is not installable", w, r, user) return } if plugin.Installed { - LocalError("This plugin has already been installed",w,r,user) + LocalError("This plugin has already been installed", w, r, user) return } var active bool err := is_plugin_active_stmt.QueryRow(uname).Scan(&active) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } var has_plugin bool = (err == nil) @@ -1094,7 +1076,7 @@ func route_panel_plugins_install(w http.ResponseWriter, r *http.Request, user Us if plugins[uname].Install != nil { err = plugins[uname].Install() if err != nil { - LocalError(err.Error(),w,r,user) + LocalError(err.Error(), w, r, user) return } } @@ -1102,26 +1084,26 @@ func route_panel_plugins_install(w http.ResponseWriter, r *http.Request, user Us if plugins[uname].Activate != nil { err = plugins[uname].Activate() if err != nil { - LocalError(err.Error(),w,r,user) + LocalError(err.Error(), w, r, user) return } } if has_plugin { - _, err = update_plugin_install_stmt.Exec(1,uname) + _, err = update_plugin_install_stmt.Exec(1, uname) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = update_plugin_stmt.Exec(1,uname) + _, err = update_plugin_stmt.Exec(1, uname) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } else { - _, err := add_plugin_stmt.Exec(uname,1,1) + _, err := add_plugin_stmt.Exec(uname, 1, 1) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } @@ -1132,47 +1114,47 @@ func route_panel_plugins_install(w http.ResponseWriter, r *http.Request, user Us plugins[uname] = plugin err = plugins[uname].Init() if err != nil { - LocalError(err.Error(),w,r,user) + LocalError(err.Error(), w, r, user) return } - http.Redirect(w,r,"/panel/plugins/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/plugins/", http.StatusSeeOther) } -func route_panel_users(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_users(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } page, _ := strconv.Atoi(r.FormValue("page")) perPage := 10 - offset, page, lastPage := page_offset(stats.Users, page, perPage) + offset, page, lastPage := pageOffset(stats.Users, page, perPage) var userList []User - rows, err := get_users_offset_stmt.Query(offset,perPage) + rows, err := get_users_offset_stmt.Query(offset, perPage) if err != nil { - InternalError(err,w) + InternalError(err, w) return } defer rows.Close() // TO-DO: Add a UserStore method for iterating over global users and global user offsets for rows.Next() { - puser := User{ID: 0,} - err := rows.Scan(&puser.ID, &puser.Name, &puser.Group, &puser.Active, &puser.Is_Super_Admin, &puser.Avatar) + puser := User{ID: 0} + err := rows.Scan(&puser.ID, &puser.Name, &puser.Group, &puser.Active, &puser.IsSuperAdmin, &puser.Avatar) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - init_user_perms(&puser) + initUserPerms(&puser) if puser.Avatar != "" { if puser.Avatar[0] == '.' { puser.Avatar = "/uploads/avatar_" + strconv.Itoa(puser.ID) + puser.Avatar } } else { - puser.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(puser.ID),1) + puser.Avatar = strings.Replace(config.Noavatar, "{id}", strconv.Itoa(puser.ID), 1) } if groups[puser.Group].Tag != "" { @@ -1180,185 +1162,185 @@ func route_panel_users(w http.ResponseWriter, r *http.Request, user User){ } else { puser.Tag = "" } - userList = append(userList,puser) + userList = append(userList, puser) } err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) return } pageList := paginate(stats.Users, perPage, 5) - pi := PanelUserPage{"User Manager",user,headerVars,stats,userList,pageList,page,lastPage,extData} - if pre_render_hooks["pre_render_panel_users"] != nil { - if run_pre_render_hook("pre_render_panel_users", w, r, &user, &pi) { + pi := PanelUserPage{"User Manager", user, headerVars, stats, userList, pageList, page, lastPage} + if preRenderHooks["pre_render_panel_users"] != nil { + if runPreRenderHook("pre_render_panel_users", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-users.html",pi) + err = templates.ExecuteTemplate(w, "panel-users.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_users_edit(w http.ResponseWriter, r *http.Request, user User, suid string){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_users_edit(w http.ResponseWriter, r *http.Request, user User, suid string) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditUser { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } uid, err := strconv.Atoi(suid) if err != nil { - LocalError("The provided User ID is not a valid number.",w,r,user) + LocalError("The provided User ID is not a valid number.", w, r, user) return } targetUser, err := users.CascadeGet(uid) if err == ErrNoRows { - LocalError("The user you're trying to edit doesn't exist.",w,r,user) + LocalError("The user you're trying to edit doesn't exist.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - if targetUser.Is_Admin && !user.Is_Admin { - LocalError("Only administrators can edit the account of an administrator.",w,r,user) + if targetUser.IsAdmin && !user.IsAdmin { + LocalError("Only administrators can edit the account of an administrator.", w, r, user) return } var groupList []interface{} for _, group := range groups[1:] { - if !user.Perms.EditUserGroupAdmin && group.Is_Admin { + if !user.Perms.EditUserGroupAdmin && group.IsAdmin { continue } - if !user.Perms.EditUserGroupSuperMod && group.Is_Mod { + if !user.Perms.EditUserGroupSuperMod && group.IsMod { continue } - groupList = append(groupList,group) + groupList = append(groupList, group) } - pi := PanelPage{"User Editor",user,headerVars,stats,groupList,targetUser} - if pre_render_hooks["pre_render_panel_edit_user"] != nil { - if run_pre_render_hook("pre_render_panel_edit_user", w, r, &user, &pi) { + pi := PanelPage{"User Editor", user, headerVars, stats, groupList, targetUser} + if preRenderHooks["pre_render_panel_edit_user"] != nil { + if runPreRenderHook("pre_render_panel_edit_user", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-user-edit.html",pi) + err = templates.ExecuteTemplate(w, "panel-user-edit.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request, user User, suid string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_users_edit_submit(w http.ResponseWriter, r *http.Request, user User, suid string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditUser { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } uid, err := strconv.Atoi(suid) if err != nil { - LocalError("The provided User ID is not a valid number.",w,r,user) + LocalError("The provided User ID is not a valid number.", w, r, user) return } targetUser, err := users.CascadeGet(uid) if err == ErrNoRows { - LocalError("The user you're trying to edit doesn't exist.",w,r,user) + LocalError("The user you're trying to edit doesn't exist.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - if targetUser.Is_Admin && !user.Is_Admin { - LocalError("Only administrators can edit the account of an administrator.",w,r,user) + if targetUser.IsAdmin && !user.IsAdmin { + LocalError("Only administrators can edit the account of an administrator.", w, r, user) return } newname := html.EscapeString(r.PostFormValue("user-name")) if newname == "" { - LocalError("You didn't put in a username.",w,r,user) + LocalError("You didn't put in a username.", w, r, user) return } newemail := html.EscapeString(r.PostFormValue("user-email")) if newemail == "" { - LocalError("You didn't put in an email address.",w,r,user) + LocalError("You didn't put in an email address.", w, r, user) return } if (newemail != targetUser.Email) && !user.Perms.EditUserEmail { - LocalError("You need the EditUserEmail permission to edit the email address of a user.",w,r,user) + LocalError("You need the EditUserEmail permission to edit the email address of a user.", w, r, user) return } newpassword := r.PostFormValue("user-password") if newpassword != "" && !user.Perms.EditUserPassword { - LocalError("You need the EditUserPassword permission to edit the password of a user.",w,r,user) + LocalError("You need the EditUserPassword permission to edit the password of a user.", w, r, user) return } newgroup, err := strconv.Atoi(r.PostFormValue("user-group")) if err != nil { - LocalError("The provided GroupID is not a valid number.",w,r,user) + LocalError("The provided GroupID is not a valid number.", w, r, user) return } - if (newgroup > groupCapCount) || (newgroup < 0) || groups[newgroup].Name=="" { - LocalError("The group you're trying to place this user in doesn't exist.",w,r,user) + if (newgroup > groupCapCount) || (newgroup < 0) || groups[newgroup].Name == "" { + LocalError("The group you're trying to place this user in doesn't exist.", w, r, user) return } - if !user.Perms.EditUserGroupAdmin && groups[newgroup].Is_Admin { - LocalError("You need the EditUserGroupAdmin permission to assign someone to an administrator group.",w,r,user) + if !user.Perms.EditUserGroupAdmin && groups[newgroup].IsAdmin { + LocalError("You need the EditUserGroupAdmin permission to assign someone to an administrator group.", w, r, user) return } - if !user.Perms.EditUserGroupSuperMod && groups[newgroup].Is_Mod { - LocalError("You need the EditUserGroupAdmin permission to assign someone to a super mod group.",w,r,user) + if !user.Perms.EditUserGroupSuperMod && groups[newgroup].IsMod { + LocalError("You need the EditUserGroupAdmin permission to assign someone to a super mod group.", w, r, user) return } - _, err = update_user_stmt.Exec(newname,newemail,newgroup,targetUser.ID) + _, err = update_user_stmt.Exec(newname, newemail, newgroup, targetUser.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } if newpassword != "" { - SetPassword(targetUser.ID,newpassword) + SetPassword(targetUser.ID, newpassword) } err = users.Load(targetUser.ID) if err != nil { - LocalError("This user no longer exists!",w,r,user) + LocalError("This user no longer exists!", w, r, user) return } - http.Redirect(w,r,"/panel/users/edit/" + strconv.Itoa(targetUser.ID),http.StatusSeeOther) + http.Redirect(w, r, "/panel/users/edit/"+strconv.Itoa(targetUser.ID), http.StatusSeeOther) } -func route_panel_groups(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_groups(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } page, _ := strconv.Atoi(r.FormValue("page")) perPage := 9 - offset, page, lastPage := page_offset(stats.Groups, page, perPage) + offset, page, lastPage := pageOffset(stats.Groups, page, perPage) // Skip the System group offset++ @@ -1371,85 +1353,85 @@ func route_panel_groups(w http.ResponseWriter, r *http.Request, user User){ } var rank string - var rank_class string - var can_edit bool - var can_delete bool = false + var rankClass string + var canEdit bool + var canDelete = false - if group.Is_Admin { + if group.IsAdmin { rank = "Admin" - rank_class = "admin" - } else if group.Is_Mod { + rankClass = "admin" + } else if group.IsMod { rank = "Mod" - rank_class = "mod" - } else if group.Is_Banned { + rankClass = "mod" + } else if group.IsBanned { rank = "Banned" - rank_class = "banned" + rankClass = "banned" } else if group.ID == 6 { rank = "Guest" - rank_class = "guest" + rankClass = "guest" } else { rank = "Member" - rank_class = "member" + rankClass = "member" } - can_edit = user.Perms.EditGroup && (!group.Is_Admin || user.Perms.EditGroupAdmin) && (!group.Is_Mod || user.Perms.EditGroupSuperMod) - groupList = append(groupList, GroupAdmin{group.ID,group.Name,rank,rank_class,can_edit,can_delete}) + canEdit = user.Perms.EditGroup && (!group.IsAdmin || user.Perms.EditGroupAdmin) && (!group.IsMod || user.Perms.EditGroupSuperMod) + groupList = append(groupList, GroupAdmin{group.ID, group.Name, rank, rankClass, canEdit, canDelete}) count++ } //log.Printf("groupList: %+v\n", groupList) pageList := paginate(stats.Groups, perPage, 5) - pi := PanelGroupPage{"Group Manager",user,headerVars,stats,groupList,pageList,page,lastPage,extData} - if pre_render_hooks["pre_render_panel_groups"] != nil { - if run_pre_render_hook("pre_render_panel_groups", w, r, &user, &pi) { + pi := PanelGroupPage{"Group Manager", user, headerVars, stats, groupList, pageList, page, lastPage} + if preRenderHooks["pre_render_panel_groups"] != nil { + if runPreRenderHook("pre_render_panel_groups", w, r, &user, &pi) { return } } - err := templates.ExecuteTemplate(w,"panel-groups.html",pi) + err := templates.ExecuteTemplate(w, "panel-groups.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_groups_edit(w http.ResponseWriter, r *http.Request, user User, sgid string){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_groups_edit(w http.ResponseWriter, r *http.Request, user User, sgid string) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditGroup { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } gid, err := strconv.Atoi(sgid) if err != nil { - LocalError("The Group ID is not a valid integer.",w,r,user) + LocalError("The Group ID is not a valid integer.", w, r, user) return } - if !group_exists(gid) { + if !groupExists(gid) { //log.Print("aaaaa monsters") - NotFound(w,r) + NotFound(w, r) return } group := groups[gid] - if group.Is_Admin && !user.Perms.EditGroupAdmin { - LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user) + if group.IsAdmin && !user.Perms.EditGroupAdmin { + LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) return } - if group.Is_Mod && !user.Perms.EditGroupSuperMod { - LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user) + if group.IsMod && !user.Perms.EditGroupSuperMod { + LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) return } var rank string - if group.Is_Admin { + if group.IsAdmin { rank = "Admin" - } else if group.Is_Mod { + } else if group.IsMod { rank = "Mod" - } else if group.Is_Banned { + } else if group.IsBanned { rank = "Banned" } else if group.ID == 6 { rank = "Guest" @@ -1457,268 +1439,269 @@ func route_panel_groups_edit(w http.ResponseWriter, r *http.Request, user User, rank = "Member" } - disable_rank := !user.Perms.EditGroupGlobalPerms || (group.ID == 6) + disableRank := !user.Perms.EditGroupGlobalPerms || (group.ID == 6) - pi := PanelEditGroupPage{"Group Editor",user,headerVars,stats,group.ID,group.Name,group.Tag,rank,disable_rank,extData} - if pre_render_hooks["pre_render_panel_edit_group"] != nil { - if run_pre_render_hook("pre_render_panel_edit_group", w, r, &user, &pi) { + pi := PanelEditGroupPage{"Group Editor", user, headerVars, stats, group.ID, group.Name, group.Tag, rank, disableRank} + if preRenderHooks["pre_render_panel_edit_group"] != nil { + if runPreRenderHook("pre_render_panel_edit_group", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-group-edit.html",pi) + err = templates.ExecuteTemplate(w, "panel-group-edit.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_groups_edit_perms(w http.ResponseWriter, r *http.Request, user User, sgid string){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_groups_edit_perms(w http.ResponseWriter, r *http.Request, user User, sgid string) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditGroup { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } gid, err := strconv.Atoi(sgid) if err != nil { - LocalError("The Group ID is not a valid integer.",w,r,user) + LocalError("The Group ID is not a valid integer.", w, r, user) return } - if !group_exists(gid) { + if !groupExists(gid) { //log.Print("aaaaa monsters") - NotFound(w,r) + NotFound(w, r) return } group := groups[gid] - if group.Is_Admin && !user.Perms.EditGroupAdmin { - LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user) + if group.IsAdmin && !user.Perms.EditGroupAdmin { + LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) return } - if group.Is_Mod && !user.Perms.EditGroupSuperMod { - LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user) + if group.IsMod && !user.Perms.EditGroupSuperMod { + LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) return } + // TO-DO: Load the phrases in bulk for efficiency? var localPerms []NameLangToggle - localPerms = append(localPerms, NameLangToggle{"ViewTopic",GetLocalPermPhrase("ViewTopic"),group.Perms.ViewTopic}) - localPerms = append(localPerms, NameLangToggle{"LikeItem",GetLocalPermPhrase("LikeItem"),group.Perms.LikeItem}) - localPerms = append(localPerms, NameLangToggle{"CreateTopic",GetLocalPermPhrase("CreateTopic"),group.Perms.CreateTopic}) + localPerms = append(localPerms, NameLangToggle{"ViewTopic", GetLocalPermPhrase("ViewTopic"), group.Perms.ViewTopic}) + localPerms = append(localPerms, NameLangToggle{"LikeItem", GetLocalPermPhrase("LikeItem"), group.Perms.LikeItem}) + localPerms = append(localPerms, NameLangToggle{"CreateTopic", GetLocalPermPhrase("CreateTopic"), group.Perms.CreateTopic}) //<-- - localPerms = append(localPerms, NameLangToggle{"EditTopic",GetLocalPermPhrase("EditTopic"),group.Perms.EditTopic}) - localPerms = append(localPerms, NameLangToggle{"DeleteTopic",GetLocalPermPhrase("DeleteTopic"),group.Perms.DeleteTopic}) - localPerms = append(localPerms, NameLangToggle{"CreateReply",GetLocalPermPhrase("CreateReply"),group.Perms.CreateReply}) - localPerms = append(localPerms, NameLangToggle{"EditReply",GetLocalPermPhrase("EditReply"),group.Perms.EditReply}) - localPerms = append(localPerms, NameLangToggle{"DeleteReply",GetLocalPermPhrase("DeleteReply"),group.Perms.DeleteReply}) - localPerms = append(localPerms, NameLangToggle{"PinTopic",GetLocalPermPhrase("PinTopic"),group.Perms.PinTopic}) - localPerms = append(localPerms, NameLangToggle{"CloseTopic",GetLocalPermPhrase("CloseTopic"),group.Perms.CloseTopic}) + localPerms = append(localPerms, NameLangToggle{"EditTopic", GetLocalPermPhrase("EditTopic"), group.Perms.EditTopic}) + localPerms = append(localPerms, NameLangToggle{"DeleteTopic", GetLocalPermPhrase("DeleteTopic"), group.Perms.DeleteTopic}) + localPerms = append(localPerms, NameLangToggle{"CreateReply", GetLocalPermPhrase("CreateReply"), group.Perms.CreateReply}) + localPerms = append(localPerms, NameLangToggle{"EditReply", GetLocalPermPhrase("EditReply"), group.Perms.EditReply}) + localPerms = append(localPerms, NameLangToggle{"DeleteReply", GetLocalPermPhrase("DeleteReply"), group.Perms.DeleteReply}) + localPerms = append(localPerms, NameLangToggle{"PinTopic", GetLocalPermPhrase("PinTopic"), group.Perms.PinTopic}) + localPerms = append(localPerms, NameLangToggle{"CloseTopic", GetLocalPermPhrase("CloseTopic"), group.Perms.CloseTopic}) var globalPerms []NameLangToggle - globalPerms = append(globalPerms, NameLangToggle{"BanUsers",GetGlobalPermPhrase("BanUsers"),group.Perms.BanUsers}) - globalPerms = append(globalPerms, NameLangToggle{"ActivateUsers",GetGlobalPermPhrase("ActivateUsers"),group.Perms.ActivateUsers}) - globalPerms = append(globalPerms, NameLangToggle{"EditUser",GetGlobalPermPhrase("EditUser"),group.Perms.EditUser}) - globalPerms = append(globalPerms, NameLangToggle{"EditUserEmail",GetGlobalPermPhrase("EditUserEmail"),group.Perms.EditUserEmail}) - globalPerms = append(globalPerms, NameLangToggle{"EditUserPassword",GetGlobalPermPhrase("EditUserPassword"),group.Perms.EditUserPassword}) - globalPerms = append(globalPerms, NameLangToggle{"EditUserGroup",GetGlobalPermPhrase("EditUserGroup"),group.Perms.EditUserGroup}) - globalPerms = append(globalPerms, NameLangToggle{"EditUserGroupSuperMod",GetGlobalPermPhrase("EditUserGroupSuperMod"),group.Perms.EditUserGroupSuperMod}) - globalPerms = append(globalPerms, NameLangToggle{"EditUserGroupAdmin",GetGlobalPermPhrase("EditUserGroupAdmin"),group.Perms.EditUserGroupAdmin}) - globalPerms = append(globalPerms, NameLangToggle{"EditGroup",GetGlobalPermPhrase("EditGroup"),group.Perms.EditGroup}) - globalPerms = append(globalPerms, NameLangToggle{"EditGroupLocalPerms",GetGlobalPermPhrase("EditGroupLocalPerms"),group.Perms.EditGroupLocalPerms}) - globalPerms = append(globalPerms, NameLangToggle{"EditGroupGlobalPerms",GetGlobalPermPhrase("EditGroupGlobalPerms"),group.Perms.EditGroupGlobalPerms}) - globalPerms = append(globalPerms, NameLangToggle{"EditGroupSuperMod",GetGlobalPermPhrase("EditGroupSuperMod"),group.Perms.EditGroupSuperMod}) - globalPerms = append(globalPerms, NameLangToggle{"EditGroupAdmin",GetGlobalPermPhrase("EditGroupAdmin"),group.Perms.EditGroupAdmin}) - globalPerms = append(globalPerms, NameLangToggle{"ManageForums",GetGlobalPermPhrase("ManageForums"),group.Perms.ManageForums}) - globalPerms = append(globalPerms, NameLangToggle{"EditSettings",GetGlobalPermPhrase("EditSettings"),group.Perms.EditSettings}) - globalPerms = append(globalPerms, NameLangToggle{"ManageThemes",GetGlobalPermPhrase("ManageThemes"),group.Perms.ManageThemes}) - globalPerms = append(globalPerms, NameLangToggle{"ManagePlugins",GetGlobalPermPhrase("ManagePlugins"),group.Perms.ManagePlugins}) - globalPerms = append(globalPerms, NameLangToggle{"ViewAdminLogs",GetGlobalPermPhrase("ViewAdminLogs"),group.Perms.ViewAdminLogs}) - globalPerms = append(globalPerms, NameLangToggle{"ViewIPs",GetGlobalPermPhrase("ViewIPs"),group.Perms.ViewIPs}) + globalPerms = append(globalPerms, NameLangToggle{"BanUsers", GetGlobalPermPhrase("BanUsers"), group.Perms.BanUsers}) + globalPerms = append(globalPerms, NameLangToggle{"ActivateUsers", GetGlobalPermPhrase("ActivateUsers"), group.Perms.ActivateUsers}) + globalPerms = append(globalPerms, NameLangToggle{"EditUser", GetGlobalPermPhrase("EditUser"), group.Perms.EditUser}) + globalPerms = append(globalPerms, NameLangToggle{"EditUserEmail", GetGlobalPermPhrase("EditUserEmail"), group.Perms.EditUserEmail}) + globalPerms = append(globalPerms, NameLangToggle{"EditUserPassword", GetGlobalPermPhrase("EditUserPassword"), group.Perms.EditUserPassword}) + globalPerms = append(globalPerms, NameLangToggle{"EditUserGroup", GetGlobalPermPhrase("EditUserGroup"), group.Perms.EditUserGroup}) + globalPerms = append(globalPerms, NameLangToggle{"EditUserGroupSuperMod", GetGlobalPermPhrase("EditUserGroupSuperMod"), group.Perms.EditUserGroupSuperMod}) + globalPerms = append(globalPerms, NameLangToggle{"EditUserGroupAdmin", GetGlobalPermPhrase("EditUserGroupAdmin"), group.Perms.EditUserGroupAdmin}) + globalPerms = append(globalPerms, NameLangToggle{"EditGroup", GetGlobalPermPhrase("EditGroup"), group.Perms.EditGroup}) + globalPerms = append(globalPerms, NameLangToggle{"EditGroupLocalPerms", GetGlobalPermPhrase("EditGroupLocalPerms"), group.Perms.EditGroupLocalPerms}) + globalPerms = append(globalPerms, NameLangToggle{"EditGroupGlobalPerms", GetGlobalPermPhrase("EditGroupGlobalPerms"), group.Perms.EditGroupGlobalPerms}) + globalPerms = append(globalPerms, NameLangToggle{"EditGroupSuperMod", GetGlobalPermPhrase("EditGroupSuperMod"), group.Perms.EditGroupSuperMod}) + globalPerms = append(globalPerms, NameLangToggle{"EditGroupAdmin", GetGlobalPermPhrase("EditGroupAdmin"), group.Perms.EditGroupAdmin}) + globalPerms = append(globalPerms, NameLangToggle{"ManageForums", GetGlobalPermPhrase("ManageForums"), group.Perms.ManageForums}) + globalPerms = append(globalPerms, NameLangToggle{"EditSettings", GetGlobalPermPhrase("EditSettings"), group.Perms.EditSettings}) + globalPerms = append(globalPerms, NameLangToggle{"ManageThemes", GetGlobalPermPhrase("ManageThemes"), group.Perms.ManageThemes}) + globalPerms = append(globalPerms, NameLangToggle{"ManagePlugins", GetGlobalPermPhrase("ManagePlugins"), group.Perms.ManagePlugins}) + globalPerms = append(globalPerms, NameLangToggle{"ViewAdminLogs", GetGlobalPermPhrase("ViewAdminLogs"), group.Perms.ViewAdminLogs}) + globalPerms = append(globalPerms, NameLangToggle{"ViewIPs", GetGlobalPermPhrase("ViewIPs"), group.Perms.ViewIPs}) - pi := PanelEditGroupPermsPage{"Group Editor",user,headerVars,stats,group.ID,group.Name,localPerms,globalPerms,extData} - if pre_render_hooks["pre_render_panel_edit_group_perms"] != nil { - if run_pre_render_hook("pre_render_panel_edit_group_perms", w, r, &user, &pi) { + pi := PanelEditGroupPermsPage{"Group Editor", user, headerVars, stats, group.ID, group.Name, localPerms, globalPerms} + if preRenderHooks["pre_render_panel_edit_group_perms"] != nil { + if runPreRenderHook("pre_render_panel_edit_group_perms", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-group-edit-perms.html",pi) + err = templates.ExecuteTemplate(w, "panel-group-edit-perms.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, user User, sgid string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_groups_edit_submit(w http.ResponseWriter, r *http.Request, user User, sgid string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditGroup { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } gid, err := strconv.Atoi(sgid) if err != nil { - LocalError("The Group ID is not a valid integer.",w,r,user) + LocalError("The Group ID is not a valid integer.", w, r, user) return } - if !group_exists(gid) { + if !groupExists(gid) { //log.Print("aaaaa monsters") - NotFound(w,r) + NotFound(w, r) return } group := groups[gid] - if group.Is_Admin && !user.Perms.EditGroupAdmin { - LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user) + if group.IsAdmin && !user.Perms.EditGroupAdmin { + LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) return } - if group.Is_Mod && !user.Perms.EditGroupSuperMod { - LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user) + if group.IsMod && !user.Perms.EditGroupSuperMod { + LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) return } gname := r.FormValue("group-name") if gname == "" { - LocalError("The group name can't be left blank.",w,r,user) + LocalError("The group name can't be left blank.", w, r, user) return } gtag := r.FormValue("group-tag") rank := r.FormValue("group-type") - var original_rank string - if group.Is_Admin { - original_rank = "Admin" - } else if group.Is_Mod { - original_rank = "Mod" - } else if group.Is_Banned { - original_rank = "Banned" + var originalRank string + if group.IsAdmin { + originalRank = "Admin" + } else if group.IsMod { + originalRank = "Mod" + } else if group.IsBanned { + originalRank = "Banned" } else if group.ID == 6 { - original_rank = "Guest" + originalRank = "Guest" } else { - original_rank = "Member" + originalRank = "Member" } - group_update_mutex.Lock() - defer group_update_mutex.Unlock() - if rank != original_rank { + groupUpdateMutex.Lock() + defer groupUpdateMutex.Unlock() + if rank != originalRank { if !user.Perms.EditGroupGlobalPerms { - LocalError("You need the EditGroupGlobalPerms permission to change the group type.",w,r,user) + LocalError("You need the EditGroupGlobalPerms permission to change the group type.", w, r, user) return } - switch(rank) { - case "Admin": - if !user.Perms.EditGroupAdmin { - LocalError("You need the EditGroupAdmin permission to designate this group as an admin group.",w,r,user) - return - } - - _, err = update_group_rank_stmt.Exec(1,1,0,gid) - if err != nil { - InternalError(err,w) - return - } - groups[gid].Is_Admin = true - groups[gid].Is_Mod = true - groups[gid].Is_Banned = false - case "Mod": - if !user.Perms.EditGroupSuperMod { - LocalError("You need the EditGroupSuperMod permission to designate this group as a super-mod group.",w,r,user) - return - } - - _, err = update_group_rank_stmt.Exec(0,1,0,gid) - if err != nil { - InternalError(err,w) - return - } - groups[gid].Is_Admin = false - groups[gid].Is_Mod = true - groups[gid].Is_Banned = false - case "Banned": - _, err = update_group_rank_stmt.Exec(0,0,1,gid) - if err != nil { - InternalError(err,w) - return - } - groups[gid].Is_Admin = false - groups[gid].Is_Mod = false - groups[gid].Is_Banned = true - case "Guest": - LocalError("You can't designate a group as a guest group.",w,r,user) + switch rank { + case "Admin": + if !user.Perms.EditGroupAdmin { + LocalError("You need the EditGroupAdmin permission to designate this group as an admin group.", w, r, user) return - case "Member": - _, err = update_group_rank_stmt.Exec(0,0,0,gid) - if err != nil { - InternalError(err,w) - return - } - groups[gid].Is_Admin = false - groups[gid].Is_Mod = false - groups[gid].Is_Banned = false - default: - LocalError("Invalid group type.",w,r,user) + } + + _, err = update_group_rank_stmt.Exec(1, 1, 0, gid) + if err != nil { + InternalError(err, w) return + } + groups[gid].IsAdmin = true + groups[gid].IsMod = true + groups[gid].IsBanned = false + case "Mod": + if !user.Perms.EditGroupSuperMod { + LocalError("You need the EditGroupSuperMod permission to designate this group as a super-mod group.", w, r, user) + return + } + + _, err = update_group_rank_stmt.Exec(0, 1, 0, gid) + if err != nil { + InternalError(err, w) + return + } + groups[gid].IsAdmin = false + groups[gid].IsMod = true + groups[gid].IsBanned = false + case "Banned": + _, err = update_group_rank_stmt.Exec(0, 0, 1, gid) + if err != nil { + InternalError(err, w) + return + } + groups[gid].IsAdmin = false + groups[gid].IsMod = false + groups[gid].IsBanned = true + case "Guest": + LocalError("You can't designate a group as a guest group.", w, r, user) + return + case "Member": + _, err = update_group_rank_stmt.Exec(0, 0, 0, gid) + if err != nil { + InternalError(err, w) + return + } + groups[gid].IsAdmin = false + groups[gid].IsMod = false + groups[gid].IsBanned = false + default: + LocalError("Invalid group type.", w, r, user) + return } } - _, err = update_group_stmt.Exec(gname,gtag,gid) + _, err = update_group_stmt.Exec(gname, gtag, gid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } groups[gid].Name = gname groups[gid].Tag = gtag - http.Redirect(w,r,"/panel/groups/edit/" + strconv.Itoa(gid),http.StatusSeeOther) + http.Redirect(w, r, "/panel/groups/edit/"+strconv.Itoa(gid), http.StatusSeeOther) } -func route_panel_groups_edit_perms_submit(w http.ResponseWriter, r *http.Request, user User, sgid string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_groups_edit_perms_submit(w http.ResponseWriter, r *http.Request, user User, sgid string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditGroup { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } gid, err := strconv.Atoi(sgid) if err != nil { - LocalError("The Group ID is not a valid integer.",w,r,user) + LocalError("The Group ID is not a valid integer.", w, r, user) return } - if !group_exists(gid) { + if !groupExists(gid) { //log.Print("aaaaa monsters o.o") - NotFound(w,r) + NotFound(w, r) return } group := groups[gid] - if group.Is_Admin && !user.Perms.EditGroupAdmin { - LocalError("You need the EditGroupAdmin permission to edit an admin group.",w,r,user) + if group.IsAdmin && !user.Perms.EditGroupAdmin { + LocalError("You need the EditGroupAdmin permission to edit an admin group.", w, r, user) return } - if group.Is_Mod && !user.Perms.EditGroupSuperMod { - LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.",w,r,user) + if group.IsMod && !user.Perms.EditGroupSuperMod { + LocalError("You need the EditGroupSuperMod permission to edit a super-mod group.", w, r, user) return } //var lpmap map[string]bool = make(map[string]bool) - var pmap map[string]bool = make(map[string]bool) + var pmap = make(map[string]bool) if user.Perms.EditGroupLocalPerms { pplist := LocalPermList for _, perm := range pplist { @@ -1738,82 +1721,82 @@ func route_panel_groups_edit_perms_submit(w http.ResponseWriter, r *http.Request pjson, err := json.Marshal(pmap) if err != nil { - LocalError("Unable to marshal the data",w,r,user) + LocalError("Unable to marshal the data", w, r, user) return } - _, err = update_group_perms_stmt.Exec(pjson,gid) + _, err = update_group_perms_stmt.Exec(pjson, gid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - err = rebuild_group_permissions(gid) + err = rebuildGroupPermissions(gid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/panel/groups/edit/perms/" + strconv.Itoa(gid),http.StatusSeeOther) + http.Redirect(w, r, "/panel/groups/edit/perms/"+strconv.Itoa(gid), http.StatusSeeOther) } -func route_panel_groups_create_submit(w http.ResponseWriter, r *http.Request, user User){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_groups_create_submit(w http.ResponseWriter, r *http.Request, user User) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.EditGroup { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } - group_name := r.PostFormValue("group-name") - if group_name == "" { - LocalError("You need a name for this group!",w,r,user) + groupName := r.PostFormValue("group-name") + if groupName == "" { + LocalError("You need a name for this group!", w, r, user) return } - group_tag := r.PostFormValue("group-tag") + groupTag := r.PostFormValue("group-tag") - var is_admin, is_mod, is_banned bool + var isAdmin, isMod, isBanned bool if user.Perms.EditGroupGlobalPerms { - group_type := r.PostFormValue("group-type") - if group_type == "Admin" { + groupType := r.PostFormValue("group-type") + if groupType == "Admin" { if !user.Perms.EditGroupAdmin { - LocalError("You need the EditGroupAdmin permission to create admin groups",w,r,user) + LocalError("You need the EditGroupAdmin permission to create admin groups", w, r, user) return } - is_admin = true - is_mod = true - } else if group_type == "Mod" { + isAdmin = true + isMod = true + } else if groupType == "Mod" { if !user.Perms.EditGroupSuperMod { - LocalError("You need the EditGroupSuperMod permission to create admin groups",w,r,user) + LocalError("You need the EditGroupSuperMod permission to create admin groups", w, r, user) return } - is_mod = true - } else if group_type == "Banned" { - is_banned = true + isMod = true + } else if groupType == "Banned" { + isBanned = true } } - gid, err := create_group(group_name, group_tag, is_admin, is_mod, is_banned) + gid, err := createGroup(groupName, groupTag, isAdmin, isMod, isBanned) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/panel/groups/edit/" + strconv.Itoa(gid),http.StatusSeeOther) + http.Redirect(w, r, "/panel/groups/edit/"+strconv.Itoa(gid), http.StatusSeeOther) } -func route_panel_themes(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_themes(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageThemes { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } @@ -1823,80 +1806,81 @@ func route_panel_themes(w http.ResponseWriter, r *http.Request, user User){ continue } if theme.ForkOf == "" { - pThemeList = append(pThemeList,theme) + pThemeList = append(pThemeList, theme) } else { - vThemeList = append(vThemeList,theme) + vThemeList = append(vThemeList, theme) } } - pi := PanelThemesPage{"Theme Manager",user,headerVars,stats,pThemeList,vThemeList,extData} - if pre_render_hooks["pre_render_panel_themes"] != nil { - if run_pre_render_hook("pre_render_panel_themes", w, r, &user, &pi) { + pi := PanelThemesPage{"Theme Manager", user, headerVars, stats, pThemeList, vThemeList} + if preRenderHooks["pre_render_panel_themes"] != nil { + if runPreRenderHook("pre_render_panel_themes", w, r, &user, &pi) { return } } - err := templates.ExecuteTemplate(w,"panel-themes.html",pi) + err := templates.ExecuteTemplate(w, "panel-themes.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_panel_themes_default(w http.ResponseWriter, r *http.Request, user User, uname string){ - _, ok := SimplePanelSessionCheck(w,r,&user) +func route_panel_themes_set_default(w http.ResponseWriter, r *http.Request, user User, uname string) { + _, ok := SimplePanelSessionCheck(w, r, &user) if !ok { return } if !user.Perms.ManageThemes { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } theme, ok := themes[uname] if !ok { - LocalError("The theme isn't registered in the system",w,r,user) + LocalError("The theme isn't registered in the system", w, r, user) return } if theme.Disabled { - LocalError("You must not enable this theme",w,r,user) + LocalError("You must not enable this theme", w, r, user) return } var isDefault bool - log.Print("uname",uname) + log.Print("uname", uname) err := is_theme_default_stmt.QueryRow(uname).Scan(&isDefault) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } - has_theme := err != ErrNoRows - if has_theme { - log.Print("isDefault",isDefault) + hasTheme := err != ErrNoRows + if hasTheme { + log.Print("isDefault", isDefault) if isDefault { - LocalError("The theme is already active",w,r,user) + LocalError("The theme is already active", w, r, user) return } - _, err = update_theme_stmt.Exec(1,uname) + _, err = update_theme_stmt.Exec(1, uname) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } else { - _, err := add_theme_stmt.Exec(uname,1) + _, err := add_theme_stmt.Exec(uname, 1) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } - _, err = update_theme_stmt.Exec(0,defaultTheme) + // TO-DO: Make this less racey + _, err = update_theme_stmt.Exec(0, defaultTheme) if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -1906,22 +1890,21 @@ func route_panel_themes_default(w http.ResponseWriter, r *http.Request, user Use dTheme, ok := themes[defaultTheme] if !ok { - InternalError(errors.New("The default theme is missing"),w) + InternalError(errors.New("The default theme is missing"), w) return } dTheme.Active = false themes[defaultTheme] = dTheme - defaultTheme = uname - reset_template_overrides() - add_theme_static_files(themes[uname]) - map_theme_templates(theme) + defaultTheme = uname // TO-DO: Make this less racey + resetTemplateOverrides() + mapThemeTemplates(theme) - http.Redirect(w,r,"/panel/themes/",http.StatusSeeOther) + http.Redirect(w, r, "/panel/themes/", http.StatusSeeOther) } -func route_panel_logs_mod(w http.ResponseWriter, r *http.Request, user User){ - headerVars, stats, ok := PanelSessionCheck(w,r,&user) +func route_panel_logs_mod(w http.ResponseWriter, r *http.Request, user User) { + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } @@ -1929,17 +1912,17 @@ func route_panel_logs_mod(w http.ResponseWriter, r *http.Request, user User){ var logCount int err := modlog_count_stmt.QueryRow().Scan(&logCount) if err != nil { - InternalError(err,w) + InternalError(err, w) return } page, _ := strconv.Atoi(r.FormValue("page")) perPage := 10 - offset, page, lastPage := page_offset(logCount, page, perPage) + offset, page, lastPage := pageOffset(logCount, page, perPage) - rows, err := get_modlogs_offset_stmt.Query(offset,perPage) + rows, err := get_modlogs_offset_stmt.Query(offset, perPage) if err != nil { - InternalError(err,w) + InternalError(err, w) return } defer rows.Close() @@ -1948,112 +1931,112 @@ func route_panel_logs_mod(w http.ResponseWriter, r *http.Request, user User){ var action, elementType, ipaddress, doneAt string var elementID, actorID int for rows.Next() { - err := rows.Scan(&action,&elementID,&elementType, &ipaddress, &actorID, &doneAt) + err := rows.Scan(&action, &elementID, &elementType, &ipaddress, &actorID, &doneAt) if err != nil { - InternalError(err,w) + InternalError(err, w) return } actor, err := users.CascadeGet(actorID) if err != nil { - actor = &User{Name:"Unknown",Link:build_profile_url("unknown",0)} + actor = &User{Name: "Unknown", Link: buildProfileURL("unknown", 0)} } - switch(action) { - case "lock": - topic, err := topics.CascadeGet(elementID) + switch action { + case "lock": + topic, err := topics.CascadeGet(elementID) + if err != nil { + topic = &Topic{Title: "Unknown", Link: buildProfileURL("unknown", 0)} + } + action = "" + topic.Title + " was locked by " + actor.Name + "" + case "unlock": + topic, err := topics.CascadeGet(elementID) + if err != nil { + topic = &Topic{Title: "Unknown", Link: buildProfileURL("unknown", 0)} + } + action = "" + topic.Title + " was reopened by " + actor.Name + "" + case "stick": + topic, err := topics.CascadeGet(elementID) + if err != nil { + topic = &Topic{Title: "Unknown", Link: buildProfileURL("unknown", 0)} + } + action = "" + topic.Title + " was pinned by " + actor.Name + "" + case "unstick": + topic, err := topics.CascadeGet(elementID) + if err != nil { + topic = &Topic{Title: "Unknown", Link: buildProfileURL("unknown", 0)} + } + action = "" + topic.Title + " was unpinned by " + actor.Name + "" + case "delete": + if elementType == "topic" { + action = "Topic #" + strconv.Itoa(elementID) + " was deleted by " + actor.Name + "" + } else { + topic, err := getTopicByReply(elementID) if err != nil { - topic = &Topic{Title:"Unknown",Link:build_profile_url("unknown",0)} + topic = &Topic{Title: "Unknown", Link: buildProfileURL("unknown", 0)} } - action = "" + topic.Title + " was locked by "+actor.Name+"" - case "unlock": - topic, err := topics.CascadeGet(elementID) - if err != nil { - topic = &Topic{Title:"Unknown",Link:build_profile_url("unknown",0)} - } - action = "" + topic.Title + " was reopened by "+actor.Name+"" - case "stick": - topic, err := topics.CascadeGet(elementID) - if err != nil { - topic = &Topic{Title:"Unknown",Link:build_profile_url("unknown",0)} - } - action = "" + topic.Title + " was pinned by "+actor.Name+"" - case "unstick": - topic, err := topics.CascadeGet(elementID) - if err != nil { - topic = &Topic{Title:"Unknown",Link:build_profile_url("unknown",0)} - } - action = "" + topic.Title + " was unpinned by "+actor.Name+"" - case "delete": - if elementType == "topic" { - action = "Topic #" + strconv.Itoa(elementID) + " was deleted by "+actor.Name+"" - } else { - topic, err := get_topic_by_reply(elementID) - if err != nil { - topic = &Topic{Title:"Unknown",Link:build_profile_url("unknown",0)} - } - action = "A reply in " + topic.Title + " was deleted by "+actor.Name+"" - } - case "ban": - targetUser, err := users.CascadeGet(elementID) - if err != nil { - targetUser = &User{Name:"Unknown",Link:build_profile_url("unknown",0)} - } - action = "" + targetUser.Name + " was banned by "+actor.Name+"" - case "unban": - targetUser, err := users.CascadeGet(elementID) - if err != nil { - targetUser = &User{Name:"Unknown",Link:build_profile_url("unknown",0)} - } - action = "" + targetUser.Name + " was unbanned by "+actor.Name+"" - case "activate": - targetUser, err := users.CascadeGet(elementID) - if err != nil { - targetUser = &User{Name:"Unknown",Link:build_profile_url("unknown",0)} - } - action = "" + targetUser.Name + " was activated by "+actor.Name+"" - default: - action = "Unknown action '" + action + "' by "+actor.Name+"" + action = "A reply in " + topic.Title + " was deleted by " + actor.Name + "" + } + case "ban": + targetUser, err := users.CascadeGet(elementID) + if err != nil { + targetUser = &User{Name: "Unknown", Link: buildProfileURL("unknown", 0)} + } + action = "" + targetUser.Name + " was banned by " + actor.Name + "" + case "unban": + targetUser, err := users.CascadeGet(elementID) + if err != nil { + targetUser = &User{Name: "Unknown", Link: buildProfileURL("unknown", 0)} + } + action = "" + targetUser.Name + " was unbanned by " + actor.Name + "" + case "activate": + targetUser, err := users.CascadeGet(elementID) + if err != nil { + targetUser = &User{Name: "Unknown", Link: buildProfileURL("unknown", 0)} + } + action = "" + targetUser.Name + " was activated by " + actor.Name + "" + default: + action = "Unknown action '" + action + "' by " + actor.Name + "" } - logs = append(logs, Log{Action:template.HTML(action),IPAddress:ipaddress,DoneAt:doneAt}) + logs = append(logs, Log{Action: template.HTML(action), IPAddress: ipaddress, DoneAt: doneAt}) } err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) return } pageList := paginate(logCount, perPage, 5) - pi := PanelLogsPage{"Moderation Logs",user,headerVars,stats,logs,pageList,page,lastPage,extData} - if pre_render_hooks["pre_render_panel_mod_log"] != nil { - if run_pre_render_hook("pre_render_panel_mod_log", w, r, &user, &pi) { + pi := PanelLogsPage{"Moderation Logs", user, headerVars, stats, logs, pageList, page, lastPage} + if preRenderHooks["pre_render_panel_mod_log"] != nil { + if runPreRenderHook("pre_render_panel_mod_log", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"panel-modlogs.html",pi) + err = templates.ExecuteTemplate(w, "panel-modlogs.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } func route_panel_debug(w http.ResponseWriter, r *http.Request, user User) { - headerVars, stats, ok := PanelSessionCheck(w,r,&user) + headerVars, stats, ok := PanelSessionCheck(w, r, &user) if !ok { return } - if !user.Is_Admin { - NoPermissions(w,r,user) + if !user.IsAdmin { + NoPermissions(w, r, user) return } uptime := "..." - db_stats := db.Stats() - open_conn_count := db_stats.OpenConnections + dbStats := db.Stats() + openConnCount := dbStats.OpenConnections // Disk I/O? - pi := PanelDebugPage{"Debug",user,headerVars,stats,uptime,open_conn_count,db_adapter,extData} - err := templates.ExecuteTemplate(w,"panel-debug.html",pi) + pi := PanelDebugPage{"Debug", user, headerVars, stats, uptime, openConnCount, dbAdapter} + err := templates.ExecuteTemplate(w, "panel-debug.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } diff --git a/permissions.go b/permissions.go index 543cd5fd..69bac172 100644 --- a/permissions.go +++ b/permissions.go @@ -5,7 +5,7 @@ import "sync" import "strconv" import "encoding/json" -var permupdate_mutex sync.Mutex +var permUpdateMutex sync.Mutex var BlankPerms Perms var BlankForumPerms ForumPerms var GuestPerms Perms @@ -14,9 +14,9 @@ var ReadReplyForumPerms ForumPerms var ReadWriteForumPerms ForumPerms var AllPerms Perms var AllForumPerms ForumPerms -var AllPluginPerms map[string]bool = make(map[string]bool) +var AllPluginPerms = make(map[string]bool) -var LocalPermList []string = []string{ +var LocalPermList = []string{ "ViewTopic", "LikeItem", "CreateTopic", @@ -29,7 +29,7 @@ var LocalPermList []string = []string{ "CloseTopic", } -var GlobalPermList []string = []string{ +var GlobalPermList = []string{ "BanUsers", "ActivateUsers", "EditUser", @@ -52,71 +52,69 @@ var GlobalPermList []string = []string{ } // Permission Structure: ActionComponent[Subcomponent]Flag -type Perms struct -{ +type Perms struct { // Global Permissions - BanUsers bool - ActivateUsers bool - EditUser bool - EditUserEmail bool - EditUserPassword bool - EditUserGroup bool + BanUsers bool + ActivateUsers bool + EditUser bool + EditUserEmail bool + EditUserPassword bool + EditUserGroup bool EditUserGroupSuperMod bool - EditUserGroupAdmin bool - EditGroup bool - EditGroupLocalPerms bool - EditGroupGlobalPerms bool - EditGroupSuperMod bool - EditGroupAdmin bool - ManageForums bool // This could be local, albeit limited for per-forum managers? - EditSettings bool - ManageThemes bool - ManagePlugins bool - ViewAdminLogs bool - ViewIPs bool + EditUserGroupAdmin bool + EditGroup bool + EditGroupLocalPerms bool + EditGroupGlobalPerms bool + EditGroupSuperMod bool + EditGroupAdmin bool + ManageForums bool // This could be local, albeit limited for per-forum managers? + EditSettings bool + ManageThemes bool + ManagePlugins bool + ViewAdminLogs bool + ViewIPs bool // Forum permissions - ViewTopic bool - LikeItem bool + ViewTopic bool + LikeItem bool CreateTopic bool - EditTopic bool + EditTopic bool DeleteTopic bool CreateReply bool //CreateReplyToOwn bool EditReply bool //EditOwnReply bool DeleteReply bool - PinTopic bool - CloseTopic bool + PinTopic bool + CloseTopic bool //CloseOwnTopic bool //ExtData map[string]bool } /* Inherit from group permissions for ones we don't have */ -type ForumPerms struct -{ - ViewTopic bool - LikeItem bool +type ForumPerms struct { + ViewTopic bool + LikeItem bool CreateTopic bool - EditTopic bool + EditTopic bool DeleteTopic bool CreateReply bool //CreateReplyToOwn bool EditReply bool //EditOwnReply bool DeleteReply bool - PinTopic bool - CloseTopic bool + PinTopic bool + CloseTopic bool //CloseOwnTopic bool Overrides bool - ExtData map[string]bool + ExtData map[string]bool } func init() { BlankPerms = Perms{ - //ExtData: make(map[string]bool), + //ExtData: make(map[string]bool), } BlankForumPerms = ForumPerms{ @@ -129,80 +127,80 @@ func init() { } AllPerms = Perms{ - BanUsers: true, - ActivateUsers: true, - EditUser: true, - EditUserEmail: true, - EditUserPassword: true, - EditUserGroup: true, + BanUsers: true, + ActivateUsers: true, + EditUser: true, + EditUserEmail: true, + EditUserPassword: true, + EditUserGroup: true, EditUserGroupSuperMod: true, - EditUserGroupAdmin: true, - EditGroup: true, - EditGroupLocalPerms: true, - EditGroupGlobalPerms: true, - EditGroupSuperMod: true, - EditGroupAdmin: true, - ManageForums: true, - EditSettings: true, - ManageThemes: true, - ManagePlugins: true, - ViewAdminLogs: true, - ViewIPs: true, + EditUserGroupAdmin: true, + EditGroup: true, + EditGroupLocalPerms: true, + EditGroupGlobalPerms: true, + EditGroupSuperMod: true, + EditGroupAdmin: true, + ManageForums: true, + EditSettings: true, + ManageThemes: true, + ManagePlugins: true, + ViewAdminLogs: true, + ViewIPs: true, - ViewTopic: true, - LikeItem: true, + ViewTopic: true, + LikeItem: true, CreateTopic: true, - EditTopic: true, + EditTopic: true, DeleteTopic: true, CreateReply: true, - EditReply: true, + EditReply: true, DeleteReply: true, - PinTopic: true, - CloseTopic: true, + PinTopic: true, + CloseTopic: true, //ExtData: make(map[string]bool), } AllForumPerms = ForumPerms{ - ViewTopic: true, - LikeItem: true, + ViewTopic: true, + LikeItem: true, CreateTopic: true, - EditTopic: true, + EditTopic: true, DeleteTopic: true, CreateReply: true, - EditReply: true, + EditReply: true, DeleteReply: true, - PinTopic: true, - CloseTopic: true, + PinTopic: true, + CloseTopic: true, Overrides: true, - ExtData: make(map[string]bool), + ExtData: make(map[string]bool), } ReadWriteForumPerms = ForumPerms{ - ViewTopic: true, - LikeItem: true, + ViewTopic: true, + LikeItem: true, CreateTopic: true, CreateReply: true, - Overrides: true, - ExtData: make(map[string]bool), + Overrides: true, + ExtData: make(map[string]bool), } ReadReplyForumPerms = ForumPerms{ - ViewTopic: true, - LikeItem: true, + ViewTopic: true, + LikeItem: true, CreateReply: true, - Overrides: true, - ExtData: make(map[string]bool), + Overrides: true, + ExtData: make(map[string]bool), } ReadForumPerms = ForumPerms{ ViewTopic: true, Overrides: true, - ExtData: make(map[string]bool), + ExtData: make(map[string]bool), } - guest_user.Perms = GuestPerms + guestUser.Perms = GuestPerms if dev.DebugMode { log.Printf("Guest Perms: %+v\n", GuestPerms) @@ -210,51 +208,51 @@ func init() { } } -func preset_to_permmap(preset string) (out map[string]ForumPerms) { +func presetToPermmap(preset string) (out map[string]ForumPerms) { out = make(map[string]ForumPerms) - switch(preset) { - case "all": - out["guests"] = ReadForumPerms - out["members"] = ReadWriteForumPerms - out["staff"] = AllForumPerms - out["admins"] = AllForumPerms - case "announce": - out["guests"] = ReadForumPerms - out["members"] = ReadReplyForumPerms - out["staff"] = AllForumPerms - out["admins"] = AllForumPerms - case "members": - out["guests"] = BlankForumPerms - out["members"] = ReadWriteForumPerms - out["staff"] = AllForumPerms - out["admins"] = AllForumPerms - case "staff": - out["guests"] = BlankForumPerms - out["members"] = BlankForumPerms - out["staff"] = ReadWriteForumPerms - out["admins"] = AllForumPerms - case "admins": - out["guests"] = BlankForumPerms - out["members"] = BlankForumPerms - out["staff"] = BlankForumPerms - out["admins"] = AllForumPerms - case "archive": - out["guests"] = ReadForumPerms - out["members"] = ReadForumPerms - out["staff"] = ReadForumPerms - out["admins"] = ReadForumPerms //CurateForumPerms. Delete / Edit but no create? - default: - out["guests"] = BlankForumPerms - out["members"] = BlankForumPerms - out["staff"] = BlankForumPerms - out["admins"] = BlankForumPerms + switch preset { + case "all": + out["guests"] = ReadForumPerms + out["members"] = ReadWriteForumPerms + out["staff"] = AllForumPerms + out["admins"] = AllForumPerms + case "announce": + out["guests"] = ReadForumPerms + out["members"] = ReadReplyForumPerms + out["staff"] = AllForumPerms + out["admins"] = AllForumPerms + case "members": + out["guests"] = BlankForumPerms + out["members"] = ReadWriteForumPerms + out["staff"] = AllForumPerms + out["admins"] = AllForumPerms + case "staff": + out["guests"] = BlankForumPerms + out["members"] = BlankForumPerms + out["staff"] = ReadWriteForumPerms + out["admins"] = AllForumPerms + case "admins": + out["guests"] = BlankForumPerms + out["members"] = BlankForumPerms + out["staff"] = BlankForumPerms + out["admins"] = AllForumPerms + case "archive": + out["guests"] = ReadForumPerms + out["members"] = ReadForumPerms + out["staff"] = ReadForumPerms + out["admins"] = ReadForumPerms //CurateForumPerms. Delete / Edit but no create? + default: + out["guests"] = BlankForumPerms + out["members"] = BlankForumPerms + out["staff"] = BlankForumPerms + out["admins"] = BlankForumPerms } return out } -func permmap_to_query(permmap map[string]ForumPerms, fid int) error { - permupdate_mutex.Lock() - defer permupdate_mutex.Unlock() +func permmapToQuery(permmap map[string]ForumPerms, fid int) error { + permUpdateMutex.Lock() + defer permUpdateMutex.Unlock() _, err := delete_forum_perms_by_forum_stmt.Exec(fid) if err != nil { @@ -265,7 +263,7 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error { if err != nil { return err } - _, err = add_forum_perms_to_forum_admins_stmt.Exec(fid,"",perms) + _, err = add_forum_perms_to_forum_admins_stmt.Exec(fid, "", perms) if err != nil { return err } @@ -274,7 +272,7 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error { if err != nil { return err } - _, err = add_forum_perms_to_forum_staff_stmt.Exec(fid,"",perms) + _, err = add_forum_perms_to_forum_staff_stmt.Exec(fid, "", perms) if err != nil { return err } @@ -283,7 +281,7 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error { if err != nil { return err } - _, err = add_forum_perms_to_forum_members_stmt.Exec(fid,"",perms) + _, err = add_forum_perms_to_forum_members_stmt.Exec(fid, "", perms) if err != nil { return err } @@ -292,15 +290,15 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error { if err != nil { return err } - _, err = add_forum_perms_to_group_stmt.Exec(6,fid,"",perms) + _, err = add_forum_perms_to_group_stmt.Exec(6, fid, "", perms) if err != nil { return err } - return rebuild_forum_permissions(fid) + return rebuildForumPermissions(fid) } -func rebuild_forum_permissions(fid int) error { +func rebuildForumPermissions(fid int) error { if dev.DebugMode { log.Print("Loading the forum permissions") } @@ -332,34 +330,34 @@ func rebuild_forum_permissions(fid int) error { } pperms.ExtData = make(map[string]bool) pperms.Overrides = true - _, ok := forum_perms[gid] + _, ok := forumPerms[gid] if !ok { - forum_perms[gid] = make(map[int]ForumPerms) + forumPerms[gid] = make(map[int]ForumPerms) } - forum_perms[gid][fid] = pperms + forumPerms[gid][fid] = pperms } - for gid, _ := range groups { + for gid := range groups { if dev.DebugMode { log.Print("Updating the forum permissions for Group #" + strconv.Itoa(gid)) } - var blank_list []ForumPerms - var blank_int_list []int - groups[gid].Forums = blank_list - groups[gid].CanSee = blank_int_list + var blankList []ForumPerms + var blankIntList []int + groups[gid].Forums = blankList + groups[gid].CanSee = blankIntList - for ffid, _ := range forums { - forum_perm, ok := forum_perms[gid][ffid] + for ffid := range forums { + forumPerm, ok := forumPerms[gid][ffid] if ok { //log.Print("Overriding permissions for forum #" + strconv.Itoa(fid)) - groups[gid].Forums = append(groups[gid].Forums,forum_perm) + groups[gid].Forums = append(groups[gid].Forums, forumPerm) } else { //log.Print("Inheriting from default for forum #" + strconv.Itoa(fid)) - forum_perm = BlankForumPerms - groups[gid].Forums = append(groups[gid].Forums,forum_perm) + forumPerm = BlankForumPerms + groups[gid].Forums = append(groups[gid].Forums, forumPerm) } - if forum_perm.Overrides { - if forum_perm.ViewTopic { + if forumPerm.Overrides { + if forumPerm.ViewTopic { groups[gid].CanSee = append(groups[gid].CanSee, ffid) } } else if groups[gid].Perms.ViewTopic { @@ -369,13 +367,13 @@ func rebuild_forum_permissions(fid int) error { if dev.SuperDebug { log.Printf("groups[gid].CanSee %+v\n", groups[gid].CanSee) log.Printf("groups[gid].Forums %+v\n", groups[gid].Forums) - log.Print("len(groups[gid].Forums)",len(groups[gid].Forums)) + log.Print("len(groups[gid].Forums)", len(groups[gid].Forums)) } } return nil } -func build_forum_permissions() error { +func buildForumPermissions() error { forums, err := fstore.GetAll() if err != nil { return err @@ -391,7 +389,7 @@ func build_forum_permissions() error { log.Print("Adding the forum permissions") } // Temporarily store the forum perms in a map before transferring it to a much faster and thread-safe slice - forum_perms = make(map[int]map[int]ForumPerms) + forumPerms = make(map[int]map[int]ForumPerms) for rows.Next() { var gid, fid int var perms []byte @@ -406,32 +404,32 @@ func build_forum_permissions() error { } pperms.ExtData = make(map[string]bool) pperms.Overrides = true - _, ok := forum_perms[gid] + _, ok := forumPerms[gid] if !ok { - forum_perms[gid] = make(map[int]ForumPerms) + forumPerms[gid] = make(map[int]ForumPerms) } - forum_perms[gid][fid] = pperms + forumPerms[gid][fid] = pperms } - for gid, _ := range groups { + for gid := range groups { if dev.DebugMode { log.Print("Adding the forum permissions for Group #" + strconv.Itoa(gid) + " - " + groups[gid].Name) } //groups[gid].Forums = append(groups[gid].Forums,BlankForumPerms) // GID 0. No longer needed now that Uncategorised occupies that slot - for fid, _ := range forums { - forum_perm, ok := forum_perms[gid][fid] + for fid := range forums { + forumPerm, ok := forumPerms[gid][fid] if ok { // Override group perms //log.Print("Overriding permissions for forum #" + strconv.Itoa(fid)) - groups[gid].Forums = append(groups[gid].Forums,forum_perm) + groups[gid].Forums = append(groups[gid].Forums, forumPerm) } else { // Inherit from Group //log.Print("Inheriting from default for forum #" + strconv.Itoa(fid)) - forum_perm = BlankForumPerms - groups[gid].Forums = append(groups[gid].Forums,forum_perm) + forumPerm = BlankForumPerms + groups[gid].Forums = append(groups[gid].Forums, forumPerm) } - if forum_perm.Overrides { - if forum_perm.ViewTopic { + if forumPerm.Overrides { + if forumPerm.ViewTopic { groups[gid].CanSee = append(groups[gid].CanSee, fid) } } else if groups[gid].Perms.ViewTopic { @@ -448,26 +446,26 @@ func build_forum_permissions() error { return nil } -func forum_perms_to_group_forum_preset(fperms ForumPerms) string { +func forumPermsToGroupForumPreset(fperms ForumPerms) string { if !fperms.Overrides { return "default" } if !fperms.ViewTopic { return "no_access" } - var can_post bool = (fperms.LikeItem && fperms.CreateTopic && fperms.CreateReply) - var can_moderate bool = (can_post && fperms.EditTopic && fperms.DeleteTopic && fperms.EditReply && fperms.DeleteReply && fperms.PinTopic && fperms.CloseTopic) - if can_moderate { + var canPost = (fperms.LikeItem && fperms.CreateTopic && fperms.CreateReply) + var canModerate = (canPost && fperms.EditTopic && fperms.DeleteTopic && fperms.EditReply && fperms.DeleteReply && fperms.PinTopic && fperms.CloseTopic) + if canModerate { return "can_moderate" } - if (fperms.EditTopic || fperms.DeleteTopic || fperms.EditReply || fperms.DeleteReply || fperms.PinTopic || fperms.CloseTopic) { - if !can_post { + if fperms.EditTopic || fperms.DeleteTopic || fperms.EditReply || fperms.DeleteReply || fperms.PinTopic || fperms.CloseTopic { + if !canPost { return "custom" } return "quasi_mod" } - if can_post { + if canPost { return "can_post" } if fperms.ViewTopic && !fperms.LikeItem && !fperms.CreateTopic && !fperms.CreateReply { @@ -476,63 +474,72 @@ func forum_perms_to_group_forum_preset(fperms ForumPerms) string { return "custom" } -func group_forum_preset_to_forum_perms(preset string) (fperms ForumPerms, changed bool) { - switch(preset) { - case "read_only": - return ReadForumPerms, true - case "can_post": - return ReadWriteForumPerms, true - case "can_moderate": - return AllForumPerms, true - case "no_access": - return ForumPerms{Overrides: true,ExtData: make(map[string]bool)}, true - case "default": - return BlankForumPerms, true +func groupForumPresetToForumPerms(preset string) (fperms ForumPerms, changed bool) { + switch preset { + case "read_only": + return ReadForumPerms, true + case "can_post": + return ReadWriteForumPerms, true + case "can_moderate": + return AllForumPerms, true + case "no_access": + return ForumPerms{Overrides: true, ExtData: make(map[string]bool)}, true + case "default": + return BlankForumPerms, true //case "custom": return fperms, false } return fperms, false } -func strip_invalid_group_forum_preset(preset string) string { - switch(preset) { - case "read_only","can_post","can_moderate","no_access","default","custom": - return preset +func stripInvalidGroupForumPreset(preset string) string { + switch preset { + case "read_only", "can_post", "can_moderate", "no_access", "default", "custom": + return preset } return "" } -func strip_invalid_preset(preset string) string { - switch(preset) { - case "all","announce","members","staff","admins","archive","custom": - break - default: return "" +func stripInvalidPreset(preset string) string { + switch preset { + case "all", "announce", "members", "staff", "admins", "archive", "custom": + return preset + default: + return "" } - return preset } -func preset_to_lang(preset string) string { - switch(preset) { - case "all": return "Public" - case "announce": return "Announcements" - case "members": return "Member Only" - case "staff": return "Staff Only" - case "admins": return "Admin Only" - case "archive": return "Archive" - case "custom": return "Custom" +// TO-DO: Move this into the phrase system? +func presetToLang(preset string) string { + switch preset { + case "all": + return "Public" + case "announce": + return "Announcements" + case "members": + return "Member Only" + case "staff": + return "Staff Only" + case "admins": + return "Admin Only" + case "archive": + return "Archive" + case "custom": + return "Custom" + default: + return "" } - return "" } -func rebuild_group_permissions(gid int) error { +func rebuildGroupPermissions(gid int) error { var permstr []byte log.Print("Reloading a group") - err := db.QueryRow("select permissions from users_groups where gid = ?",gid).Scan(&permstr) + err := db.QueryRow("select permissions from users_groups where gid = ?", gid).Scan(&permstr) if err != nil { return err } tmp_perms := Perms{ - //ExtData: make(map[string]bool), + //ExtData: make(map[string]bool), } err = json.Unmarshal(permstr, &tmp_perms) if err != nil { @@ -543,7 +550,7 @@ func rebuild_group_permissions(gid int) error { return nil } -func override_perms(perms *Perms, status bool) { +func overridePerms(perms *Perms, status bool) { if status { *perms = AllPerms } else { @@ -552,7 +559,7 @@ func override_perms(perms *Perms, status bool) { } // TO-DO: We need a better way of overriding forum perms rather than setting them one by one -func override_forum_perms(perms *Perms, status bool) { +func overrideForumPerms(perms *Perms, status bool) { perms.ViewTopic = status perms.LikeItem = status perms.CreateTopic = status @@ -565,10 +572,10 @@ func override_forum_perms(perms *Perms, status bool) { perms.CloseTopic = status } -func register_plugin_perm(name string) { +func registerPluginPerm(name string) { AllPluginPerms[name] = true } -func deregister_plugin_perm(name string) { - delete(AllPluginPerms,name) +func deregisterPluginPerm(name string) { + delete(AllPluginPerms, name) } diff --git a/phrases.go b/phrases.go index e4106732..94255e0c 100644 --- a/phrases.go +++ b/phrases.go @@ -1,101 +1,102 @@ +/* +* +* Gosora Phrase System +* Copyright Azareal 2017 - 2018 +* + */ package main -import "sync" +import ( + "sync" + "sync/atomic" +) -// I wish we had constant maps x.x -var phrase_mutex sync.RWMutex -var perm_phrase_mutex sync.RWMutex -var change_langpack_mutex sync.Mutex -var currentLanguage string = "english" -var currentLangPack *LanguagePack +// TO-DO: Let the admin edit phrases from inside the Control Panel? How should we persist these? Should we create a copy of the langpack or edit the primaries? Use the changeLangpack mutex for this? +var changeLangpackMutex sync.Mutex +var currentLanguage = "english" +var currentLangPack atomic.Value -type LevelPhrases struct -{ - Level string - LevelMax string +type LevelPhrases struct { + Level string + LevelMax string - // Override the phrase for individual levels, if the phrases exist - Levels []string // index = level + // Override the phrase for individual levels, if the phrases exist + Levels []string // index = level } -type LanguagePack struct -{ - Name string - Phrases map[string]string // Should we use a sync map or a struct for these? It would be nice, if we could keep all the phrases consistent. - LevelPhrases LevelPhrases +type LanguagePack struct { + Name string + Phrases map[string]string // Should we use a sync map or a struct for these? It would be nice, if we could keep all the phrases consistent. + LevelPhrases LevelPhrases GlobalPermPhrases map[string]string - LocalPermPhrases map[string]string + LocalPermPhrases map[string]string + SettingLabels map[string]string } // TO-DO: Move the english language pack into it's own file and just keep the common logic here -var langpacks map[string]*LanguagePack = map[string]*LanguagePack{ +var langpacks = map[string]*LanguagePack{ "english": &LanguagePack{ Name: "english", // We'll be implementing the level phrases in the software proper very very soon! LevelPhrases: LevelPhrases{ - Level: "Level {0}", + Level: "Level {0}", LevelMax: "", // Add a max level setting? }, GlobalPermPhrases: map[string]string{ - "BanUsers": "Can ban users", - "ActivateUsers": "Can activate users", - "EditUser": "Can edit users", - "EditUserEmail": "Can change a user's email", - "EditUserPassword": "Can change a user's password", - "EditUserGroup": "Can change a user's group", + "BanUsers": "Can ban users", + "ActivateUsers": "Can activate users", + "EditUser": "Can edit users", + "EditUserEmail": "Can change a user's email", + "EditUserPassword": "Can change a user's password", + "EditUserGroup": "Can change a user's group", "EditUserGroupSuperMod": "Can edit super-mods", - "EditUserGroupAdmin": "Can edit admins", - "EditGroup": "Can edit groups", - "EditGroupLocalPerms": "Can edit a group's minor perms", - "EditGroupGlobalPerms": "Can edit a group's global perms", - "EditGroupSuperMod": "Can edit super-mod groups", - "EditGroupAdmin": "Can edit admin groups", - "ManageForums": "Can manage forums", - "EditSettings": "Can edit settings", - "ManageThemes": "Can manage themes", - "ManagePlugins": "Can manage plugins", - "ViewAdminLogs": "Can view the administrator action logs", - "ViewIPs": "Can view IP addresses", + "EditUserGroupAdmin": "Can edit admins", + "EditGroup": "Can edit groups", + "EditGroupLocalPerms": "Can edit a group's minor perms", + "EditGroupGlobalPerms": "Can edit a group's global perms", + "EditGroupSuperMod": "Can edit super-mod groups", + "EditGroupAdmin": "Can edit admin groups", + "ManageForums": "Can manage forums", + "EditSettings": "Can edit settings", + "ManageThemes": "Can manage themes", + "ManagePlugins": "Can manage plugins", + "ViewAdminLogs": "Can view the administrator action logs", + "ViewIPs": "Can view IP addresses", }, LocalPermPhrases: map[string]string{ - "ViewTopic": "Can view topics", - "LikeItem": "Can like items", + "ViewTopic": "Can view topics", + "LikeItem": "Can like items", "CreateTopic": "Can create topics", - "EditTopic": "Can edit topics", + "EditTopic": "Can edit topics", "DeleteTopic": "Can delete topics", "CreateReply": "Can create replies", - "EditReply": "Can edit replies", + "EditReply": "Can edit replies", "DeleteReply": "Can delete replies", - "PinTopic": "Can pin topics", - "CloseTopic": "Can lock topics", + "PinTopic": "Can pin topics", + "CloseTopic": "Can lock topics", + }, + + SettingLabels: map[string]string{ + "activation_type": "Activate All,Email Activation,Admin Approval", }, }, } func init() { - currentLangPack = langpacks[currentLanguage] + currentLangPack.Store(langpacks[currentLanguage]) } // We might not need to use a mutex for this, we shouldn't need to change the phrases after start-up, and when we do we could overwrite the entire map -func GetPhrase(name string) (string,bool) { - phrase_mutex.RLock() - defer perm_phrase_mutex.RUnlock() - res, ok := currentLangPack.Phrases[name] - return res, ok -} - -func GetPhraseUnsafe(name string) (string,bool) { - res, ok := currentLangPack.Phrases[name] +func GetPhrase(name string) (string, bool) { + res, ok := currentLangPack.Load().(*LanguagePack).Phrases[name] return res, ok } func GetGlobalPermPhrase(name string) string { - perm_phrase_mutex.RLock() - defer perm_phrase_mutex.RUnlock() - res, ok := currentLangPack.GlobalPermPhrases[name] + res, ok := currentLangPack.Load().(*LanguagePack).GlobalPermPhrases[name] if !ok { return "{name}" } @@ -103,31 +104,46 @@ func GetGlobalPermPhrase(name string) string { } func GetLocalPermPhrase(name string) string { - perm_phrase_mutex.RLock() - defer perm_phrase_mutex.RUnlock() - res, ok := currentLangPack.LocalPermPhrases[name] + res, ok := currentLangPack.Load().(*LanguagePack).LocalPermPhrases[name] if !ok { return "{name}" } return res } +func GetSettingLabel(name string) string { + res, ok := currentLangPack.Load().(*LanguagePack).SettingLabels[name] + if !ok { + return "{name}" + } + return res +} + +// Is this a copy of the map or a pointer to it? We don't want to accidentally create a race condition +func GetAllSettingLabels() map[string]string { + return currentLangPack.Load().(*LanguagePack).SettingLabels +} + +// Use runtime reflection for updating phrases? func AddPhrase() { } +func UpdatePhrase() { +} func DeletePhrase() { } +// TO-DO: Use atomics to store the pointer of the current active langpack? func ChangeLanguagePack(name string) (exists bool) { - change_langpack_mutex.Lock() + changeLangpackMutex.Lock() pack, ok := langpacks[name] if !ok { - change_langpack_mutex.Unlock() + changeLangpackMutex.Unlock() return false } - currentLangPack = pack - change_langpack_mutex.Unlock() + currentLangPack.Store(pack) + changeLangpackMutex.Unlock() return true } diff --git a/plugin_bbcode.go b/plugin_bbcode.go index 183eb910..bf7a27fd 100644 --- a/plugin_bbcode.go +++ b/plugin_bbcode.go @@ -1,172 +1,175 @@ package main -//import "log" -//import "fmt" -import "bytes" -//import "strings" -import "strconv" -import "regexp" -import "time" -import "math/rand" +import ( + //"log" + //"fmt" + "bytes" + + //"strings" + "math/rand" + "regexp" + "strconv" + "time" +) var random *rand.Rand -var bbcode_invalid_number []byte -var bbcode_no_negative []byte -var bbcode_missing_tag []byte +var bbcodeInvalidNumber []byte +var bbcodeNoNegative []byte +var bbcodeMissingTag []byte -var bbcode_bold *regexp.Regexp -var bbcode_italic *regexp.Regexp -var bbcode_underline *regexp.Regexp -var bbcode_strikethrough *regexp.Regexp -var bbcode_url *regexp.Regexp -var bbcode_url_label *regexp.Regexp -var bbcode_quotes *regexp.Regexp -var bbcode_code *regexp.Regexp +var bbcodeBold *regexp.Regexp +var bbcodeItalic *regexp.Regexp +var bbcodeUnderline *regexp.Regexp +var bbcodeStrikethrough *regexp.Regexp +var bbcodeURL *regexp.Regexp +var bbcodeURLLabel *regexp.Regexp +var bbcodeQuotes *regexp.Regexp +var bbcodeCode *regexp.Regexp func init() { - plugins["bbcode"] = NewPlugin("bbcode","BBCode","Azareal","http://github.com/Azareal","","","",init_bbcode,nil,deactivate_bbcode,nil,nil) + plugins["bbcode"] = NewPlugin("bbcode", "BBCode", "Azareal", "http://github.com/Azareal", "", "", "", initBbcode, nil, deactivateBbcode, nil, nil) } -func init_bbcode() error { +func initBbcode() error { //plugins["bbcode"].AddHook("parse_assign", bbcode_parse_without_code) - plugins["bbcode"].AddHook("parse_assign", bbcode_full_parse) + plugins["bbcode"].AddHook("parse_assign", bbcodeFullParse) - bbcode_invalid_number = []byte("[Invalid Number]") - bbcode_no_negative = []byte("[No Negative Numbers]") - bbcode_missing_tag = []byte("[Missing Tag]") + bbcodeInvalidNumber = []byte("[Invalid Number]") + bbcodeNoNegative = []byte("[No Negative Numbers]") + bbcodeMissingTag = []byte("[Missing Tag]") - bbcode_bold = regexp.MustCompile(`(?s)\[b\](.*)\[/b\]`) - bbcode_italic = regexp.MustCompile(`(?s)\[i\](.*)\[/i\]`) - bbcode_underline = regexp.MustCompile(`(?s)\[u\](.*)\[/u\]`) - bbcode_strikethrough = regexp.MustCompile(`(?s)\[s\](.*)\[/s\]`) + bbcodeBold = regexp.MustCompile(`(?s)\[b\](.*)\[/b\]`) + bbcodeItalic = regexp.MustCompile(`(?s)\[i\](.*)\[/i\]`) + bbcodeUnderline = regexp.MustCompile(`(?s)\[u\](.*)\[/u\]`) + bbcodeStrikethrough = regexp.MustCompile(`(?s)\[s\](.*)\[/s\]`) urlpattern := `(http|https|ftp|mailto*)(:??)\/\/([\.a-zA-Z\/]+)` - bbcode_url = regexp.MustCompile(`\[url\]` + urlpattern + `\[/url\]`) - bbcode_url_label = regexp.MustCompile(`(?s)\[url=` + urlpattern + `\](.*)\[/url\]`) - bbcode_quotes = regexp.MustCompile(`\[quote\](.*)\[/quote\]`) - bbcode_code = regexp.MustCompile(`\[code\](.*)\[/code\]`) + bbcodeURL = regexp.MustCompile(`\[url\]` + urlpattern + `\[/url\]`) + bbcodeURLLabel = regexp.MustCompile(`(?s)\[url=` + urlpattern + `\](.*)\[/url\]`) + bbcodeQuotes = regexp.MustCompile(`\[quote\](.*)\[/quote\]`) + bbcodeCode = regexp.MustCompile(`\[code\](.*)\[/code\]`) random = rand.New(rand.NewSource(time.Now().UnixNano())) return nil } -func deactivate_bbcode() { +func deactivateBbcode() { //plugins["bbcode"].RemoveHook("parse_assign", bbcode_parse_without_code) - plugins["bbcode"].RemoveHook("parse_assign", bbcode_full_parse) + plugins["bbcode"].RemoveHook("parse_assign", bbcodeFullParse) } -func bbcode_regex_parse(msg string) string { - msg = bbcode_bold.ReplaceAllString(msg,"$1") - msg = bbcode_italic.ReplaceAllString(msg,"$1") - msg = bbcode_underline.ReplaceAllString(msg,"$1") - msg = bbcode_strikethrough.ReplaceAllString(msg,"$1") - msg = bbcode_url.ReplaceAllString(msg,"$1$2//$3") - msg = bbcode_url_label.ReplaceAllString(msg,"$4") - msg = bbcode_quotes.ReplaceAllString(msg,"$1") - //msg = bbcode_code.ReplaceAllString(msg,"$1") +func bbcodeRegexParse(msg string) string { + msg = bbcodeBold.ReplaceAllString(msg, "$1") + msg = bbcodeItalic.ReplaceAllString(msg, "$1") + msg = bbcodeUnderline.ReplaceAllString(msg, "$1") + msg = bbcodeStrikethrough.ReplaceAllString(msg, "$1") + msg = bbcodeURL.ReplaceAllString(msg, "$1$2//$3") + msg = bbcodeURLLabel.ReplaceAllString(msg, "$4") + msg = bbcodeQuotes.ReplaceAllString(msg, "$1") + //msg = bbcodeCode.ReplaceAllString(msg,"$1") return msg } // Only does the simple BBCode like [u], [b], [i] and [s] -func bbcode_simple_parse(msg string) string { - var has_u, has_b, has_i, has_s bool +func bbcodeSimpleParse(msg string) string { + var hasU, hasB, hasI, hasS bool msgbytes := []byte(msg) for i := 0; (i + 2) < len(msgbytes); i++ { - if msgbytes[i] == '[' && msgbytes[i + 2] == ']' { - if msgbytes[i + 1] == 'b' && !has_b { + if msgbytes[i] == '[' && msgbytes[i+2] == ']' { + if msgbytes[i+1] == 'b' && !hasB { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_b = true - } else if msgbytes[i + 1] == 'i' && !has_i { + msgbytes[i+2] = '>' + hasB = true + } else if msgbytes[i+1] == 'i' && !hasI { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_i = true - } else if msgbytes[i + 1] == 'u' && !has_u { + msgbytes[i+2] = '>' + hasI = true + } else if msgbytes[i+1] == 'u' && !hasU { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_u = true - } else if msgbytes[i + 1] == 's' && !has_s { + msgbytes[i+2] = '>' + hasU = true + } else if msgbytes[i+1] == 's' && !hasS { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_s = true + msgbytes[i+2] = '>' + hasS = true } i += 2 } } // There's an unclosed tag in there x.x - if has_i || has_u || has_b || has_s { - close_under := []byte("") - close_italic := []byte("") - close_bold := []byte("") - close_strike := []byte("") - if has_i { - msgbytes = append(msgbytes, close_italic...) + if hasI || hasU || hasB || hasS { + closeUnder := []byte("") + closeItalic := []byte("") + closeBold := []byte("") + closeStrike := []byte("") + if hasI { + msgbytes = append(msgbytes, closeItalic...) } - if has_u { - msgbytes = append(msgbytes, close_under...) + if hasU { + msgbytes = append(msgbytes, closeUnder...) } - if has_b { - msgbytes = append(msgbytes, close_bold...) + if hasB { + msgbytes = append(msgbytes, closeBold...) } - if has_s { - msgbytes = append(msgbytes, close_strike...) + if hasS { + msgbytes = append(msgbytes, closeStrike...) } } return string(msgbytes) } // Here for benchmarking purposes. Might add a plugin setting for disabling [code] as it has it's paws everywhere -func bbcode_parse_without_code(msg string) string { - var has_u, has_b, has_i, has_s bool - var complex_bbc bool +func bbcodeParseWithoutCode(msg string) string { + var hasU, hasB, hasI, hasS bool + var complexBbc bool msgbytes := []byte(msg) for i := 0; (i + 3) < len(msgbytes); i++ { if msgbytes[i] == '[' { - if msgbytes[i + 2] != ']' { - if msgbytes[i + 1] == '/' { - if msgbytes[i + 3] == ']' { - if msgbytes[i + 2] == 'b' { + if msgbytes[i+2] != ']' { + if msgbytes[i+1] == '/' { + if msgbytes[i+3] == ']' { + if msgbytes[i+2] == 'b' { msgbytes[i] = '<' - msgbytes[i + 3] = '>' - has_b = false - } else if msgbytes[i + 2] == 'i' { + msgbytes[i+3] = '>' + hasB = false + } else if msgbytes[i+2] == 'i' { msgbytes[i] = '<' - msgbytes[i + 3] = '>' - has_i = false - } else if msgbytes[i + 2] == 'u' { + msgbytes[i+3] = '>' + hasI = false + } else if msgbytes[i+2] == 'u' { msgbytes[i] = '<' - msgbytes[i + 3] = '>' - has_u = false - } else if msgbytes[i + 2] == 's' { + msgbytes[i+3] = '>' + hasU = false + } else if msgbytes[i+2] == 's' { msgbytes[i] = '<' - msgbytes[i + 3] = '>' - has_s = false + msgbytes[i+3] = '>' + hasS = false } i += 3 } else { - complex_bbc = true + complexBbc = true } } else { - complex_bbc = true + complexBbc = true } } else { - if msgbytes[i + 1] == 'b' && !has_b { + if msgbytes[i+1] == 'b' && !hasB { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_b = true - } else if msgbytes[i + 1] == 'i' && !has_i { + msgbytes[i+2] = '>' + hasB = true + } else if msgbytes[i+1] == 'i' && !hasI { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_i = true - } else if msgbytes[i + 1] == 'u' && !has_u { + msgbytes[i+2] = '>' + hasI = true + } else if msgbytes[i+1] == 'u' && !hasU { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_u = true - } else if msgbytes[i + 1] == 's' && !has_s { + msgbytes[i+2] = '>' + hasU = true + } else if msgbytes[i+1] == 's' && !hasS { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_s = true + msgbytes[i+2] = '>' + hasS = true } i += 2 } @@ -174,74 +177,75 @@ func bbcode_parse_without_code(msg string) string { } // There's an unclosed tag in there x.x - if has_i || has_u || has_b || has_s { - close_under := []byte("") - close_italic := []byte("") - close_bold := []byte("") - close_strike := []byte("") - if has_i { - msgbytes = append(bytes.TrimSpace(msgbytes), close_italic...) + if hasI || hasU || hasB || hasS { + closeUnder := []byte("") + closeItalic := []byte("") + closeBold := []byte("") + closeStrike := []byte("") + if hasI { + msgbytes = append(bytes.TrimSpace(msgbytes), closeItalic...) } - if has_u { - msgbytes = append(bytes.TrimSpace(msgbytes), close_under...) + if hasU { + msgbytes = append(bytes.TrimSpace(msgbytes), closeUnder...) } - if has_b { - msgbytes = append(bytes.TrimSpace(msgbytes), close_bold...) + if hasB { + msgbytes = append(bytes.TrimSpace(msgbytes), closeBold...) } - if has_s { - msgbytes = append(bytes.TrimSpace(msgbytes), close_strike...) + if hasS { + msgbytes = append(bytes.TrimSpace(msgbytes), closeStrike...) } } // Copy the new complex parser over once the rough edges have been smoothed over - if complex_bbc { - msg = bbcode_url.ReplaceAllString(msg,"$1$2//$3") - msg = bbcode_url_label.ReplaceAllString(msg,"$4") - msg = bbcode_quotes.ReplaceAllString(msg,"$1") - msg = bbcode_code.ReplaceAllString(msg,"$1") + if complexBbc { + msg = string(msgbytes) + msg = bbcodeURL.ReplaceAllString(msg, "$1$2//$3") + msg = bbcodeURLLabel.ReplaceAllString(msg, "$4") + msg = bbcodeQuotes.ReplaceAllString(msg, "$1") + return bbcodeCode.ReplaceAllString(msg, "$1") + } else { + return string(msgbytes) } - - return string(msgbytes) } // Does every type of BBCode -func bbcode_full_parse(msg string) string { - var has_u, has_b, has_i, has_s, has_c bool - var complex_bbc bool +func bbcodeFullParse(msg string) string { + var hasU, hasB, hasI, hasS, hasC bool + var complexBbc bool msgbytes := []byte(msg) - msgbytes = append(msgbytes,space_gap...) + msgbytes = append(msgbytes, spaceGap...) //log.Print("BBCode Simple Pre:","`"+string(msgbytes)+"`") //log.Print("----") for i := 0; i < len(msgbytes); i++ { if msgbytes[i] == '[' { - if msgbytes[i + 2] != ']' { - if msgbytes[i + 1] == '/' { - if msgbytes[i + 3] == ']' { - if !has_c { - if msgbytes[i + 2] == 'b' { + if msgbytes[i+2] != ']' { + if msgbytes[i+1] == '/' { + if msgbytes[i+3] == ']' { + if !hasC { + if msgbytes[i+2] == 'b' { msgbytes[i] = '<' - msgbytes[i + 3] = '>' - has_b = false - } else if msgbytes[i + 2] == 'i' { + msgbytes[i+3] = '>' + hasB = false + } else if msgbytes[i+2] == 'i' { msgbytes[i] = '<' - msgbytes[i + 3] = '>' - has_i = false - } else if msgbytes[i + 2] == 'u' { + msgbytes[i+3] = '>' + hasI = false + } else if msgbytes[i+2] == 'u' { msgbytes[i] = '<' - msgbytes[i + 3] = '>' - has_u = false - } else if msgbytes[i + 2] == 's' { + msgbytes[i+3] = '>' + hasU = false + } else if msgbytes[i+2] == 's' { msgbytes[i] = '<' - msgbytes[i + 3] = '>' - has_s = false + msgbytes[i+3] = '>' + hasS = false } i += 3 } } else { if msgbytes[i+2] == 'c' && msgbytes[i+3] == 'o' && msgbytes[i+4] == 'd' && msgbytes[i+5] == 'e' && msgbytes[i+6] == ']' { - has_c = false + hasC = false i += 7 } //if msglen >= (i+6) { @@ -250,36 +254,36 @@ func bbcode_full_parse(msg string) string { // log.Print(i+6) // log.Print(string(msgbytes[i:i+6])) //} - complex_bbc = true + complexBbc = true } } else { if msgbytes[i+1] == 'c' && msgbytes[i+2] == 'o' && msgbytes[i+3] == 'd' && msgbytes[i+4] == 'e' && msgbytes[i+5] == ']' { - has_c = true + hasC = true i += 6 } //if msglen >= (i+5) { // log.Print("boo2") // log.Print(string(msgbytes[i:i+5])) //} - complex_bbc = true + complexBbc = true } - } else if !has_c { - if msgbytes[i + 1] == 'b' && !has_b { + } else if !hasC { + if msgbytes[i+1] == 'b' && !hasB { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_b = true - } else if msgbytes[i + 1] == 'i' && !has_i { + msgbytes[i+2] = '>' + hasB = true + } else if msgbytes[i+1] == 'i' && !hasI { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_i = true - } else if msgbytes[i + 1] == 'u' && !has_u { + msgbytes[i+2] = '>' + hasI = true + } else if msgbytes[i+1] == 'u' && !hasU { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_u = true - } else if msgbytes[i + 1] == 's' && !has_s { + msgbytes[i+2] = '>' + hasU = true + } else if msgbytes[i+1] == 's' && !hasS { msgbytes[i] = '<' - msgbytes[i + 2] = '>' - has_s = true + msgbytes[i+2] = '>' + hasS = true } i += 2 } @@ -287,86 +291,86 @@ func bbcode_full_parse(msg string) string { } // There's an unclosed tag in there somewhere x.x - if has_i || has_u || has_b || has_s { - close_under := []byte("") - close_italic := []byte("") - close_bold := []byte("") - close_strike := []byte("") - if has_i { - msgbytes = append(bytes.TrimSpace(msgbytes), close_italic...) + if hasI || hasU || hasB || hasS { + closeUnder := []byte("") + closeItalic := []byte("") + closeBold := []byte("") + closeStrike := []byte("") + if hasI { + msgbytes = append(bytes.TrimSpace(msgbytes), closeItalic...) } - if has_u { - msgbytes = append(bytes.TrimSpace(msgbytes), close_under...) + if hasU { + msgbytes = append(bytes.TrimSpace(msgbytes), closeUnder...) } - if has_b { - msgbytes = append(bytes.TrimSpace(msgbytes), close_bold...) + if hasB { + msgbytes = append(bytes.TrimSpace(msgbytes), closeBold...) } - if has_s { - msgbytes = append(bytes.TrimSpace(msgbytes), close_strike...) + if hasS { + msgbytes = append(bytes.TrimSpace(msgbytes), closeStrike...) } - msgbytes = append(msgbytes,space_gap...) + msgbytes = append(msgbytes, spaceGap...) } - if complex_bbc { + if complexBbc { i := 0 var start, lastTag int var outbytes []byte //log.Print("BBCode Pre:","`"+string(msgbytes)+"`") //log.Print("----") for ; i < len(msgbytes); i++ { - MainLoop: + MainLoop: if msgbytes[i] == '[' { - OuterComplex: - if msgbytes[i + 1] == 'u' { + OuterComplex: + if msgbytes[i+1] == 'u' { if msgbytes[i+2] == 'r' && msgbytes[i+3] == 'l' && msgbytes[i+4] == ']' { start = i + 5 outbytes = append(outbytes, msgbytes[lastTag:i]...) i = start - i += partial_url_bytes_len(msgbytes[start:]) + i += partialURLBytesLen(msgbytes[start:]) //log.Print("Partial Bytes:",string(msgbytes[start:])) //log.Print("-----") - if !bytes.Equal(msgbytes[i:i+6],[]byte("[/url]")) { + if !bytes.Equal(msgbytes[i:i+6], []byte("[/url]")) { //log.Print("Invalid Bytes:",string(msgbytes[i:i+6])) //log.Print("-----") - outbytes = append(outbytes, invalid_url...) + outbytes = append(outbytes, invalidURL...) goto MainLoop } - outbytes = append(outbytes, url_open...) + outbytes = append(outbytes, urlOpen...) outbytes = append(outbytes, msgbytes[start:i]...) - outbytes = append(outbytes, url_open2...) + outbytes = append(outbytes, urlOpen2...) outbytes = append(outbytes, msgbytes[start:i]...) - outbytes = append(outbytes, url_close...) + outbytes = append(outbytes, urlClose...) i += 6 lastTag = i } - } else if msgbytes[i + 1] == 'r' { - if bytes.Equal(msgbytes[i+2:i+6],[]byte("and]")) { + } else if msgbytes[i+1] == 'r' { + if bytes.Equal(msgbytes[i+2:i+6], []byte("and]")) { outbytes = append(outbytes, msgbytes[lastTag:i]...) start = i + 6 i = start - for ;; i++ { + for ; ; i++ { if msgbytes[i] == '[' { - if !bytes.Equal(msgbytes[i+1:i+7],[]byte("/rand]")) { - outbytes = append(outbytes, bbcode_missing_tag...) + if !bytes.Equal(msgbytes[i+1:i+7], []byte("/rand]")) { + outbytes = append(outbytes, bbcodeMissingTag...) goto OuterComplex } break } else if (len(msgbytes) - 1) < (i + 10) { - outbytes = append(outbytes, bbcode_missing_tag...) - goto OuterComplex + outbytes = append(outbytes, bbcodeMissingTag...) + goto OuterComplex } } - number, err := strconv.ParseInt(string(msgbytes[start:i]),10,64) + number, err := strconv.ParseInt(string(msgbytes[start:i]), 10, 64) if err != nil { - outbytes = append(outbytes, bbcode_invalid_number...) + outbytes = append(outbytes, bbcodeInvalidNumber...) goto MainLoop } // TO-DO: Add support for negative numbers? if number < 0 { - outbytes = append(outbytes, bbcode_no_negative...) + outbytes = append(outbytes, bbcodeNoNegative...) goto MainLoop } @@ -374,7 +378,7 @@ func bbcode_full_parse(msg string) string { if number == 0 { dat = []byte("0") } else { - dat = []byte(strconv.FormatInt((random.Int63n(number)),10)) + dat = []byte(strconv.FormatInt((random.Int63n(number)), 10)) } outbytes = append(outbytes, dat...) @@ -395,17 +399,17 @@ func bbcode_full_parse(msg string) string { if len(outbytes) != 0 { //log.Print("BBCode Post:",`"`+string(outbytes[0:len(outbytes) - 10])+`"`) //log.Print("----") - msg = string(outbytes[0:len(outbytes) - 10]) + msg = string(outbytes[0 : len(outbytes)-10]) } else { - msg = string(msgbytes[0:len(msgbytes) - 10]) + msg = string(msgbytes[0 : len(msgbytes)-10]) } //msg = bbcode_url.ReplaceAllString(msg,"$1$2//$3") - msg = bbcode_url_label.ReplaceAllString(msg,"$4") - msg = bbcode_quotes.ReplaceAllString(msg,"$1") - msg = bbcode_code.ReplaceAllString(msg,"$1") + msg = bbcodeURLLabel.ReplaceAllString(msg, "$4") + msg = bbcodeQuotes.ReplaceAllString(msg, "$1") + msg = bbcodeCode.ReplaceAllString(msg, "$1") } else { - msg = string(msgbytes[0:len(msgbytes) - 10]) + msg = string(msgbytes[0 : len(msgbytes)-10]) } return msg diff --git a/plugin_helloworld.go b/plugin_helloworld.go index 3580bb03..60f8d6f4 100644 --- a/plugin_helloworld.go +++ b/plugin_helloworld.go @@ -1,20 +1,20 @@ package main func init() { - plugins["helloworld"] = NewPlugin("helloworld","Hello World","Azareal","http://github.com/Azareal","","","",init_helloworld,nil,deactivate_helloworld,nil,nil) + plugins["helloworld"] = NewPlugin("helloworld", "Hello World", "Azareal", "http://github.com/Azareal", "", "", "", initHelloworld, nil, deactivateHelloworld, nil, nil) } // init_helloworld is separate from init() as we don't want the plugin to run if the plugin is disabled -func init_helloworld() error { - plugins["helloworld"].AddHook("rrow_assign", helloworld_reply) +func initHelloworld() error { + plugins["helloworld"].AddHook("rrow_assign", helloworldReply) return nil } -func deactivate_helloworld() { - plugins["helloworld"].RemoveHook("rrow_assign", helloworld_reply) +func deactivateHelloworld() { + plugins["helloworld"].RemoveHook("rrow_assign", helloworldReply) } -func helloworld_reply(data interface{}) interface{} { +func helloworldReply(data interface{}) interface{} { reply := data.(*Reply) reply.Content = "Hello World!" reply.ContentHtml = "Hello World!" diff --git a/plugin_markdown.go b/plugin_markdown.go index 325c56a9..b87c7ecd 100644 --- a/plugin_markdown.go +++ b/plugin_markdown.go @@ -4,73 +4,72 @@ package main import "regexp" import "strings" -var markdown_max_depth int = 25 // How deep the parser will go when parsing Markdown strings -var markdown_unclosed_element []byte +var markdownMaxDepth int = 25 // How deep the parser will go when parsing Markdown strings +var markdownUnclosedElement []byte -var markdown_bold_tag_open, markdown_bold_tag_close []byte -var markdown_italic_tag_open, markdown_italic_tag_close []byte -var markdown_underline_tag_open, markdown_underline_tag_close []byte -var markdown_strike_tag_open, markdown_strike_tag_close []byte +var markdownBoldTagOpen, markdownBoldTagClose []byte +var markdownItalicTagOpen, markdownItalicTagClose []byte +var markdownUnderlineTagOpen, markdownUnderlineTagClose []byte +var markdownStrikeTagOpen, markdownStrikeTagClose []byte -var markdown_bold_italic *regexp.Regexp -var markdown_bold *regexp.Regexp -var markdown_italic *regexp.Regexp -var markdown_strike *regexp.Regexp -var markdown_underline *regexp.Regexp +var markdownBoldItalic *regexp.Regexp +var markdownBold *regexp.Regexp +var markdownItalic *regexp.Regexp +var markdownStrike *regexp.Regexp +var markdownUnderline *regexp.Regexp func init() { - plugins["markdown"] = NewPlugin("markdown","Markdown","Azareal","http://github.com/Azareal","","","",init_markdown,nil,deactivate_markdown,nil,nil) + plugins["markdown"] = NewPlugin("markdown", "Markdown", "Azareal", "http://github.com/Azareal", "", "", "", initMarkdown, nil, deactivateMarkdown, nil, nil) } -func init_markdown() error { - //plugins["markdown"].AddHook("parse_assign", markdown_regex_parse) - plugins["markdown"].AddHook("parse_assign", markdown_parse) +func initMarkdown() error { + //plugins["markdown"].AddHook("parse_assign", markdownRegexParse) + plugins["markdown"].AddHook("parse_assign", markdownParse) - markdown_unclosed_element = []byte("[Unclosed Element]") + markdownUnclosedElement = []byte("[Unclosed Element]") - markdown_bold_tag_open = []byte("") - markdown_bold_tag_close = []byte("") - markdown_italic_tag_open = []byte("") - markdown_italic_tag_close = []byte("") - markdown_underline_tag_open = []byte("") - markdown_underline_tag_close = []byte("") - markdown_strike_tag_open = []byte("") - markdown_strike_tag_close = []byte("") + markdownBoldTagOpen = []byte("") + markdownBoldTagClose = []byte("") + markdownItalicTagOpen = []byte("") + markdownItalicTagClose = []byte("") + markdownUnderlineTagOpen = []byte("") + markdownUnderlineTagClose = []byte("") + markdownStrikeTagOpen = []byte("") + markdownStrikeTagClose = []byte("") - markdown_bold_italic = regexp.MustCompile(`\*\*\*(.*)\*\*\*`) - markdown_bold = regexp.MustCompile(`\*\*(.*)\*\*`) - markdown_italic = regexp.MustCompile(`\*(.*)\*`) - //markdown_strike = regexp.MustCompile(`\~\~(.*)\~\~`) - markdown_strike = regexp.MustCompile(`\~(.*)\~`) + markdownBoldItalic = regexp.MustCompile(`\*\*\*(.*)\*\*\*`) + markdownBold = regexp.MustCompile(`\*\*(.*)\*\*`) + markdownItalic = regexp.MustCompile(`\*(.*)\*`) + //markdownStrike = regexp.MustCompile(`\~\~(.*)\~\~`) + markdownStrike = regexp.MustCompile(`\~(.*)\~`) //markdown_underline = regexp.MustCompile(`\_\_(.*)\_\_`) - markdown_underline = regexp.MustCompile(`\_(.*)\_`) + markdownUnderline = regexp.MustCompile(`\_(.*)\_`) return nil } -func deactivate_markdown() { - //plugins["markdown"].RemoveHook("parse_assign", markdown_regex_parse) - plugins["markdown"].RemoveHook("parse_assign", markdown_parse) +func deactivateMarkdown() { + //plugins["markdown"].RemoveHook("parse_assign", markdownRegexParse) + plugins["markdown"].RemoveHook("parse_assign", markdownParse) } -func markdown_regex_parse(msg string) string { - msg = markdown_bold_italic.ReplaceAllString(msg,"$1") - msg = markdown_bold.ReplaceAllString(msg,"$1") - msg = markdown_italic.ReplaceAllString(msg,"$1") - msg = markdown_strike.ReplaceAllString(msg,"$1") - msg = markdown_underline.ReplaceAllString(msg,"$1") +func markdownRegexParse(msg string) string { + msg = markdownBoldItalic.ReplaceAllString(msg, "$1") + msg = markdownBold.ReplaceAllString(msg, "$1") + msg = markdownItalic.ReplaceAllString(msg, "$1") + msg = markdownStrike.ReplaceAllString(msg, "$1") + msg = markdownUnderline.ReplaceAllString(msg, "$1") return msg } - // An adapter for the parser, so that the parser can call itself recursively. // This is less for the simple Markdown elements like bold and italics and more for the really complicated ones I plan on adding at some point. -func markdown_parse(msg string) string { - return strings.TrimSpace(_markdown_parse(msg + " ",0)) +func markdownParse(msg string) string { + return strings.TrimSpace(_markdownParse(msg+" ", 0)) } // Under Construction! -func _markdown_parse(msg string, n int) string { - if n > markdown_max_depth { +func _markdownParse(msg string, n int) string { + if n > markdownMaxDepth { return "[Markdown Error: Overflowed the max depth of 20]" } @@ -87,205 +86,205 @@ func _markdown_parse(msg string, n int) string { //log.Print("--OUTER MARKDOWN LOOP END--") //log.Print(" ")*/ - switch(msg[index]) { - case '_': - var startIndex int = index - if (index + 1) >= len(msg) { - break - } + switch msg[index] { + case '_': + var startIndex int = index + if (index + 1) >= len(msg) { + break + } - index++ - index = markdown_skip_until_char(msg, index, '_') - if (index - (startIndex + 1)) < 2 || index >= len(msg) { - break - } + index++ + index = markdownSkipUntilChar(msg, index, '_') + if (index-(startIndex+1)) < 2 || index >= len(msg) { + break + } - sIndex := startIndex + 1 - lIndex := index - index++ + sIndex := startIndex + 1 + lIndex := index + index++ - outbytes = append(outbytes, msg[lastElement:startIndex]...) - outbytes = append(outbytes, markdown_underline_tag_open...) - outbytes = append(outbytes, msg[sIndex:lIndex]...) - outbytes = append(outbytes, markdown_underline_tag_close...) + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdownUnderlineTagOpen...) + outbytes = append(outbytes, msg[sIndex:lIndex]...) + outbytes = append(outbytes, markdownUnderlineTagClose...) - lastElement = index - index-- - case '~': - var startIndex int = index - if (index + 1) >= len(msg) { - break - } + lastElement = index + index-- + case '~': + var startIndex int = index + if (index + 1) >= len(msg) { + break + } - index++ - index = markdown_skip_until_char(msg, index, '~') - if (index - (startIndex + 1)) < 2 || index >= len(msg) { - break - } + index++ + index = markdownSkipUntilChar(msg, index, '~') + if (index-(startIndex+1)) < 2 || index >= len(msg) { + break + } - sIndex := startIndex + 1 - lIndex := index - index++ + sIndex := startIndex + 1 + lIndex := index + index++ - outbytes = append(outbytes, msg[lastElement:startIndex]...) - outbytes = append(outbytes, markdown_strike_tag_open...) - outbytes = append(outbytes, msg[sIndex:lIndex]...) - outbytes = append(outbytes, markdown_strike_tag_close...) + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdownStrikeTagOpen...) + outbytes = append(outbytes, msg[sIndex:lIndex]...) + outbytes = append(outbytes, markdownStrikeTagClose...) - lastElement = index - index-- - case '*': - //log.Print("------") - //log.Print("[]byte(msg):",[]byte(msg)) - //log.Print("len(msg)",len(msg)) - //log.Print("start index",index) - //log.Print("start msg[index]",msg[index]) - //log.Print("start string(msg[index])",string(msg[index])) - //log.Print("start []byte(msg[:index])",[]byte(msg[:index])) + lastElement = index + index-- + case '*': + //log.Print("------") + //log.Print("[]byte(msg):",[]byte(msg)) + //log.Print("len(msg)",len(msg)) + //log.Print("start index",index) + //log.Print("start msg[index]",msg[index]) + //log.Print("start string(msg[index])",string(msg[index])) + //log.Print("start []byte(msg[:index])",[]byte(msg[:index])) - var startIndex int = index - var italic bool = true - var bold bool - if (index + 2) < len(msg) { - //log.Print("start index + 1",index + 1) - //log.Print("start msg[index]",msg[index + 1]) - //log.Print("start string(msg[index])",string(msg[index + 1])) + var startIndex int = index + var italic bool = true + var bold bool + if (index + 2) < len(msg) { + //log.Print("start index + 1",index + 1) + //log.Print("start msg[index]",msg[index + 1]) + //log.Print("start string(msg[index])",string(msg[index + 1])) - if msg[index + 1] == '*' { - //log.Print("two asterisks") - bold = true - index++ - if msg[index + 1] != '*' { - italic = false - } else { - //log.Print("three asterisks") - index++ - } - } - } - - //log.Print("lastElement",lastElement) - //log.Print("startIndex:",startIndex) - //log.Print("msg[startIndex]",msg[startIndex]) - //log.Print("string(msg[startIndex])",string(msg[startIndex])) - - //log.Print("preabrupt index",index) - //log.Print("preabrupt msg[index]",msg[index]) - //log.Print("preabrupt string(msg[index])",string(msg[index])) - //log.Print("preabrupt []byte(msg[:index])",[]byte(msg[:index])) - //log.Print("preabrupt msg[:index]",msg[:index]) - - // Does the string terminate abruptly? - if (index + 1) >= len(msg) { - break - } - - index++ - - //log.Print("preskip index",index) - //log.Print("preskip msg[index]",msg[index]) - //log.Print("preskip string(msg[index])",string(msg[index])) - - index = markdown_skip_until_asterisk(msg,index) - - if index >= len(msg) { - break - } - - //log.Print("index",index) - //log.Print("[]byte(msg[:index])",[]byte(msg[:index])) - //log.Print("msg[index]",msg[index]) - - sIndex := startIndex - lIndex := index - if bold && italic { - //log.Print("bold & italic final code") - if (index + 3) >= len(msg) { - //log.Print("unclosed markdown element @ exit element") - outbytes = append(outbytes, msg[lastElement:startIndex]...) - outbytes = append(outbytes, markdown_unclosed_element...) - lastElement = startIndex - break - } - index += 3 - sIndex += 3 - } else if bold { - //log.Print("bold final code") - if (index + 2) >= len(msg) { - //log.Print("true unclosed markdown element @ exit element") - outbytes = append(outbytes, msg[lastElement:startIndex]...) - outbytes = append(outbytes, markdown_unclosed_element...) - lastElement = startIndex - break - } - index += 2 - sIndex += 2 - } else { - //log.Print("italic final code") - if (index + 1) >= len(msg) { - //log.Print("true unclosed markdown element @ exit element") - outbytes = append(outbytes, msg[lastElement:startIndex]...) - outbytes = append(outbytes, markdown_unclosed_element...) - lastElement = startIndex - break - } + if msg[index+1] == '*' { + //log.Print("two asterisks") + bold = true index++ - sIndex++ + if msg[index+1] != '*' { + italic = false + } else { + //log.Print("three asterisks") + index++ + } } + } - //log.Print("sIndex",sIndex) - //log.Print("lIndex",lIndex) + //log.Print("lastElement",lastElement) + //log.Print("startIndex:",startIndex) + //log.Print("msg[startIndex]",msg[startIndex]) + //log.Print("string(msg[startIndex])",string(msg[startIndex])) - if lIndex <= sIndex { - //log.Print("unclosed markdown element @ lIndex <= sIndex") + //log.Print("preabrupt index",index) + //log.Print("preabrupt msg[index]",msg[index]) + //log.Print("preabrupt string(msg[index])",string(msg[index])) + //log.Print("preabrupt []byte(msg[:index])",[]byte(msg[:index])) + //log.Print("preabrupt msg[:index]",msg[:index]) + + // Does the string terminate abruptly? + if (index + 1) >= len(msg) { + break + } + + index++ + + //log.Print("preskip index",index) + //log.Print("preskip msg[index]",msg[index]) + //log.Print("preskip string(msg[index])",string(msg[index])) + + index = markdownSkipUntilAsterisk(msg, index) + + if index >= len(msg) { + break + } + + //log.Print("index",index) + //log.Print("[]byte(msg[:index])",[]byte(msg[:index])) + //log.Print("msg[index]",msg[index]) + + sIndex := startIndex + lIndex := index + if bold && italic { + //log.Print("bold & italic final code") + if (index + 3) >= len(msg) { + //log.Print("unclosed markdown element @ exit element") outbytes = append(outbytes, msg[lastElement:startIndex]...) - outbytes = append(outbytes, markdown_unclosed_element...) + outbytes = append(outbytes, markdownUnclosedElement...) lastElement = startIndex break } - - if sIndex < 0 || lIndex < 0 { - //log.Print("unclosed markdown element @ sIndex < 0 || lIndex < 0") + index += 3 + sIndex += 3 + } else if bold { + //log.Print("bold final code") + if (index + 2) >= len(msg) { + //log.Print("true unclosed markdown element @ exit element") outbytes = append(outbytes, msg[lastElement:startIndex]...) - outbytes = append(outbytes, markdown_unclosed_element...) + outbytes = append(outbytes, markdownUnclosedElement...) lastElement = startIndex break } + index += 2 + sIndex += 2 + } else { + //log.Print("italic final code") + if (index + 1) >= len(msg) { + //log.Print("true unclosed markdown element @ exit element") + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdownUnclosedElement...) + lastElement = startIndex + break + } + index++ + sIndex++ + } - //log.Print("final sIndex",sIndex) - //log.Print("final lIndex",lIndex) - //log.Print("final index",index) - //log.Print("final msg[index]",msg[index]) - //log.Print("final string(msg[index])",string(msg[index])) - - //log.Print("final msg[sIndex]",msg[sIndex]) - //log.Print("final string(msg[sIndex])",string(msg[sIndex])) - //log.Print("final msg[lIndex]",msg[lIndex]) - //log.Print("final string(msg[lIndex])",string(msg[lIndex])) - - //log.Print("[]byte(msg[:sIndex])",[]byte(msg[:sIndex])) - //log.Print("[]byte(msg[:lIndex])",[]byte(msg[:lIndex])) + //log.Print("sIndex",sIndex) + //log.Print("lIndex",lIndex) + if lIndex <= sIndex { + //log.Print("unclosed markdown element @ lIndex <= sIndex") outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdownUnclosedElement...) + lastElement = startIndex + break + } - if bold { - outbytes = append(outbytes, markdown_bold_tag_open...) - } - if italic { - outbytes = append(outbytes, markdown_italic_tag_open...) - } + if sIndex < 0 || lIndex < 0 { + //log.Print("unclosed markdown element @ sIndex < 0 || lIndex < 0") + outbytes = append(outbytes, msg[lastElement:startIndex]...) + outbytes = append(outbytes, markdownUnclosedElement...) + lastElement = startIndex + break + } - outbytes = append(outbytes, msg[sIndex:lIndex]...) + //log.Print("final sIndex",sIndex) + //log.Print("final lIndex",lIndex) + //log.Print("final index",index) + //log.Print("final msg[index]",msg[index]) + //log.Print("final string(msg[index])",string(msg[index])) - if italic { - outbytes = append(outbytes, markdown_italic_tag_close...) - } - if bold { - outbytes = append(outbytes, markdown_bold_tag_close...) - } + //log.Print("final msg[sIndex]",msg[sIndex]) + //log.Print("final string(msg[sIndex])",string(msg[sIndex])) + //log.Print("final msg[lIndex]",msg[lIndex]) + //log.Print("final string(msg[lIndex])",string(msg[lIndex])) - lastElement = index - index-- + //log.Print("[]byte(msg[:sIndex])",[]byte(msg[:sIndex])) + //log.Print("[]byte(msg[:lIndex])",[]byte(msg[:lIndex])) + + outbytes = append(outbytes, msg[lastElement:startIndex]...) + + if bold { + outbytes = append(outbytes, markdownBoldTagOpen...) + } + if italic { + outbytes = append(outbytes, markdownItalicTagOpen...) + } + + outbytes = append(outbytes, msg[sIndex:lIndex]...) + + if italic { + outbytes = append(outbytes, markdownItalicTagClose...) + } + if bold { + outbytes = append(outbytes, markdownBoldTagClose...) + } + + lastElement = index + index-- //case '`': //case '_': //case '~': @@ -303,7 +302,7 @@ func _markdown_parse(msg string, n int) string { return string(outbytes) } -func markdown_find_char(data string ,index int ,char byte) bool { +func markdownFindChar(data string, index int, char byte) bool { for ; index < len(data); index++ { item := data[index] if item > 32 { @@ -313,7 +312,7 @@ func markdown_find_char(data string ,index int ,char byte) bool { return false } -func markdown_skip_until_char(data string, index int, char byte) int { +func markdownSkipUntilChar(data string, index int, char byte) int { for ; index < len(data); index++ { if data[index] == char { break @@ -322,22 +321,23 @@ func markdown_skip_until_char(data string, index int, char byte) int { return index } -func markdown_skip_until_asterisk(data string, index int) int { +func markdownSkipUntilAsterisk(data string, index int) int { SwitchLoop: for ; index < len(data); index++ { - switch(data[index]) { - case 10: - if ((index+1) < len(data)) && markdown_find_char(data,index,'*') { - index = markdown_skip_list(data,index) - } - case '*': break SwitchLoop + switch data[index] { + case 10: + if ((index + 1) < len(data)) && markdownFindChar(data, index, '*') { + index = markdownSkipList(data, index) + } + case '*': + break SwitchLoop } } return index } // plugin_markdown doesn't support lists yet, but I want it to be easy to have nested lists when we do have them -func markdown_skip_list(data string, index int) int { +func markdownSkipList(data string, index int) int { var lastNewline int var datalen int = len(data) diff --git a/plugin_skeleton.go b/plugin_skeleton.go index 784ed438..fc7c8dc6 100644 --- a/plugin_skeleton.go +++ b/plugin_skeleton.go @@ -26,12 +26,12 @@ func init() { That Uninstallation field which is currently unused is for not only deactivating this plugin, but for purging any data associated with it such a new tables or data produced by the end-user. */ - plugins["skeleton"] = NewPlugin("skeleton","Skeleton","Azareal","","","","",init_skeleton, activate_skeleton, deactivate_skeleton,nil,nil) + plugins["skeleton"] = NewPlugin("skeleton", "Skeleton", "Azareal", "", "", "", "", initSkeleton, activateSkeleton, deactivateSkeleton, nil, nil) } -func init_skeleton() error { return nil; } +func initSkeleton() error { return nil } // Any errors encountered while trying to activate the plugin are reported back to the admin and the activation is aborted -func activate_skeleton() error { return nil; } +func activateSkeleton() error { return nil } -func deactivate_skeleton() {} +func deactivateSkeleton() {} diff --git a/plugin_socialgroups.go b/plugin_socialgroups.go index 8175f133..b172c94c 100644 --- a/plugin_socialgroups.go +++ b/plugin_socialgroups.go @@ -3,151 +3,148 @@ package main import ( //"fmt" "bytes" - "strings" - "strconv" - "errors" "context" - "net/http" + "database/sql" + "errors" "html" "html/template" - "database/sql" + "net/http" + "strconv" + "strings" "./query_gen/lib" ) -var socialgroups_list_stmt *sql.Stmt -var socialgroups_member_list_stmt *sql.Stmt -var socialgroups_member_list_join_stmt *sql.Stmt -var socialgroups_get_member_stmt *sql.Stmt -var socialgroups_get_group_stmt *sql.Stmt -var socialgroups_create_group_stmt *sql.Stmt -var socialgroups_attach_forum_stmt *sql.Stmt -var socialgroups_unattach_forum_stmt *sql.Stmt -var socialgroups_add_member_stmt *sql.Stmt +var socialgroupsListStmt *sql.Stmt +var socialgroupsMemberListStmt *sql.Stmt +var socialgroupsMemberListJoinStmt *sql.Stmt +var socialgroupsGetMemberStmt *sql.Stmt +var socialgroupsGetGroupStmt *sql.Stmt +var socialgroupsCreateGroupStmt *sql.Stmt +var socialgroupsAttachForumStmt *sql.Stmt +var socialgroupsUnattachForumStmt *sql.Stmt +var socialgroupsAddMemberStmt *sql.Stmt // TO-DO: Add a better way of splitting up giant plugins like this -type SocialGroup struct -{ - ID int - Link string - Name string - Desc string - Active bool + +// SocialGroup is a struct representing a social group +type SocialGroup struct { + ID int + Link string + Name string + Desc string + Active bool Privacy int /* 0: Public, 1: Protected, 2: Private */ // Who should be able to accept applications and create invites? Mods+ or just admins? Mods is a good start, we can ponder over whether we should make this more flexible in the future. - Joinable int /* 0: Private, 1: Anyone can join, 2: Applications, 3: Invite-only */ + Joinable int /* 0: Private, 1: Anyone can join, 2: Applications, 3: Invite-only */ - MemberCount int - Owner int - Backdrop string - CreatedAt string + MemberCount int + Owner int + Backdrop string + CreatedAt string LastUpdateTime string MainForumID int - MainForum *Forum - Forums []*Forum - ExtData ExtData + MainForum *Forum + Forums []*Forum + ExtData ExtData } -type SocialGroupPage struct -{ - Title string +type SocialGroupPage struct { + Title string CurrentUser User - Header HeaderVars - ItemList []*TopicsRow - Forum Forum - SocialGroup SocialGroup - Page int - LastPage int - ExtData ExtData + Header *HeaderVars + ItemList []*TopicsRow + Forum Forum + SocialGroup *SocialGroup + Page int + LastPage int } -type SocialGroupListPage struct -{ - Title string +// SocialGroupListPage is a page struct for constructing a list of every social group +type SocialGroupListPage struct { + Title string CurrentUser User - Header HeaderVars - GroupList []SocialGroup - ExtData ExtData + Header *HeaderVars + GroupList []*SocialGroup } -type SocialGroupMemberListPage struct -{ - Title string +type SocialGroupMemberListPage struct { + Title string CurrentUser User - Header HeaderVars - ItemList []SocialGroupMember - SocialGroup SocialGroup - Page int - LastPage int - ExtData ExtData + Header *HeaderVars + ItemList []SocialGroupMember + SocialGroup *SocialGroup + Page int + LastPage int } -type SocialGroupMember struct -{ - Link string - Rank int /* 0: Member. 1: Mod. 2: Admin. */ +// SocialGroupMember is a struct representing a specific member of a group, not to be confused with the global User struct. +type SocialGroupMember struct { + Link string + Rank int /* 0: Member. 1: Mod. 2: Admin. */ RankString string /* Member, Mod, Admin, Owner */ - PostCount int - JoinedAt string - Offline bool // TO-DO: Need to track the online states of members when WebSockets are enabled + PostCount int + JoinedAt string + Offline bool // TO-DO: Need to track the online states of members when WebSockets are enabled User User } +// TO-DO: Add a plugin interface instead of having a bunch of argument to AddPlugin? func init() { - plugins["socialgroups"] = NewPlugin("socialgroups","Social Groups","Azareal","http://github.com/Azareal","","","",init_socialgroups,nil,deactivate_socialgroups,install_socialgroups,nil) + plugins["socialgroups"] = NewPlugin("socialgroups", "Social Groups", "Azareal", "http://github.com/Azareal", "", "", "", initSocialgroups, nil, deactivateSocialgroups, installSocialgroups, nil) } -func init_socialgroups() (err error) { - plugins["socialgroups"].AddHook("intercept_build_widgets", socialgroups_widgets) - plugins["socialgroups"].AddHook("trow_assign", socialgroups_trow_assign) - plugins["socialgroups"].AddHook("topic_create_pre_loop", socialgroups_topic_create_pre_loop) - plugins["socialgroups"].AddHook("pre_render_view_forum", socialgroups_pre_render_view_forum) - plugins["socialgroups"].AddHook("simple_forum_check_pre_perms", socialgroups_forum_check) - plugins["socialgroups"].AddHook("forum_check_pre_perms", socialgroups_forum_check) +func initSocialgroups() (err error) { + plugins["socialgroups"].AddHook("intercept_build_widgets", socialgroupsWidgets) + plugins["socialgroups"].AddHook("trow_assign", socialgroupsTrowAssign) + plugins["socialgroups"].AddHook("topic_create_pre_loop", socialgroupsTopicCreatePreLoop) + plugins["socialgroups"].AddHook("pre_render_view_forum", socialgroupsPreRenderViewForum) + plugins["socialgroups"].AddHook("simple_forum_check_pre_perms", socialgroupsForumCheck) + plugins["socialgroups"].AddHook("forum_check_pre_perms", socialgroupsForumCheck) // TO-DO: Auto-grant this perm to admins upon installation? - register_plugin_perm("CreateSocialGroup") - router.HandleFunc("/groups/", socialgroups_group_list) - router.HandleFunc("/group/", socialgroups_view_group) - router.HandleFunc("/group/create/", socialgroups_create_group) - router.HandleFunc("/group/create/submit/", socialgroups_create_group_submit) - router.HandleFunc("/group/members/", socialgroups_member_list) + registerPluginPerm("CreateSocialGroup") + router.HandleFunc("/groups/", socialgroupsGroupList) + router.HandleFunc("/group/", socialgroupsViewGroup) + router.HandleFunc("/group/create/", socialgroupsCreateGroup) + router.HandleFunc("/group/create/submit/", socialgroupsCreateGroupSubmit) + router.HandleFunc("/group/members/", socialgroupsMemberList) - socialgroups_list_stmt, err = qgen.Builder.SimpleSelect("socialgroups","sgid, name, desc, active, privacy, joinable, owner, memberCount, createdAt, lastUpdateTime","","","") + socialgroupsListStmt, err = qgen.Builder.SimpleSelect("socialgroups", "sgid, name, desc, active, privacy, joinable, owner, memberCount, createdAt, lastUpdateTime", "", "", "") if err != nil { return err } - socialgroups_get_group_stmt, err = qgen.Builder.SimpleSelect("socialgroups","name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime","sgid = ?","","") + socialgroupsGetGroupStmt, err = qgen.Builder.SimpleSelect("socialgroups", "name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime", "sgid = ?", "", "") if err != nil { return err } - socialgroups_member_list_stmt, err = qgen.Builder.SimpleSelect("socialgroups_members","sgid, uid, rank, posts, joinedAt","","","") + socialgroupsMemberListStmt, err = qgen.Builder.SimpleSelect("socialgroups_members", "sgid, uid, rank, posts, joinedAt", "", "", "") if err != nil { return err } - socialgroups_member_list_join_stmt, err = qgen.Builder.SimpleLeftJoin("socialgroups_members","users","users.uid, socialgroups_members.rank, socialgroups_members.posts, socialgroups_members.joinedAt, users.name, users.avatar","socialgroups_members.uid = users.uid","socialgroups_members.sgid = ?","socialgroups_members.rank DESC, socialgroups_members.joinedat ASC","") + socialgroupsMemberListJoinStmt, err = qgen.Builder.SimpleLeftJoin("socialgroups_members", "users", "users.uid, socialgroups_members.rank, socialgroups_members.posts, socialgroups_members.joinedAt, users.name, users.avatar", "socialgroups_members.uid = users.uid", "socialgroups_members.sgid = ?", "socialgroups_members.rank DESC, socialgroups_members.joinedat ASC", "") if err != nil { return err } - socialgroups_get_member_stmt, err = qgen.Builder.SimpleSelect("socialgroups_members","rank, posts, joinedAt","sgid = ? AND uid = ?","","") + socialgroupsGetMemberStmt, err = qgen.Builder.SimpleSelect("socialgroups_members", "rank, posts, joinedAt", "sgid = ? AND uid = ?", "", "") if err != nil { return err } - socialgroups_create_group_stmt, err = qgen.Builder.SimpleInsert("socialgroups","name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime","?,?,?,?,1,?,1,?,'',UTC_TIMESTAMP(),UTC_TIMESTAMP()") + socialgroupsCreateGroupStmt, err = qgen.Builder.SimpleInsert("socialgroups", "name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime", "?,?,?,?,1,?,1,?,'',UTC_TIMESTAMP(),UTC_TIMESTAMP()") if err != nil { return err } - socialgroups_attach_forum_stmt, err = qgen.Builder.SimpleUpdate("forums","parentID = ?, parentType = 'socialgroup'","fid = ?") + socialgroupsAttachForumStmt, err = qgen.Builder.SimpleUpdate("forums", "parentID = ?, parentType = 'socialgroup'", "fid = ?") if err != nil { return err } - socialgroups_unattach_forum_stmt, err = qgen.Builder.SimpleUpdate("forums","parentID = 0, parentType = ''","fid = ?") + socialgroupsUnattachForumStmt, err = qgen.Builder.SimpleUpdate("forums", "parentID = 0, parentType = ''", "fid = ?") if err != nil { return err } - socialgroups_add_member_stmt, err = qgen.Builder.SimpleInsert("socialgroups_members","sgid, uid, rank, posts, joinedAt","?,?,?,0,UTC_TIMESTAMP()") + socialgroupsAddMemberStmt, err = qgen.Builder.SimpleInsert("socialgroups_members", "sgid, uid, rank, posts, joinedAt", "?,?,?,0,UTC_TIMESTAMP()") if err != nil { return err } @@ -155,92 +152,92 @@ func init_socialgroups() (err error) { return nil } -func deactivate_socialgroups() { - plugins["socialgroups"].RemoveHook("intercept_build_widgets", socialgroups_widgets) - plugins["socialgroups"].RemoveHook("trow_assign", socialgroups_trow_assign) - plugins["socialgroups"].RemoveHook("topic_create_pre_loop", socialgroups_topic_create_pre_loop) - plugins["socialgroups"].RemoveHook("pre_render_view_forum", socialgroups_pre_render_view_forum) - plugins["socialgroups"].RemoveHook("simple_forum_check_pre_perms", socialgroups_forum_check) - plugins["socialgroups"].RemoveHook("forum_check_pre_perms", socialgroups_forum_check) - deregister_plugin_perm("CreateSocialGroup") +func deactivateSocialgroups() { + plugins["socialgroups"].RemoveHook("intercept_build_widgets", socialgroupsWidgets) + plugins["socialgroups"].RemoveHook("trow_assign", socialgroupsTrowAssign) + plugins["socialgroups"].RemoveHook("topic_create_pre_loop", socialgroupsTopicCreatePreLoop) + plugins["socialgroups"].RemoveHook("pre_render_view_forum", socialgroupsPreRenderViewForum) + plugins["socialgroups"].RemoveHook("simple_forum_check_pre_perms", socialgroupsForumCheck) + plugins["socialgroups"].RemoveHook("forum_check_pre_perms", socialgroupsForumCheck) + deregisterPluginPerm("CreateSocialGroup") _ = router.RemoveFunc("/groups/") _ = router.RemoveFunc("/group/") _ = router.RemoveFunc("/group/create/") _ = router.RemoveFunc("/group/create/submit/") - _ = socialgroups_list_stmt.Close() - _ = socialgroups_member_list_stmt.Close() - _ = socialgroups_member_list_join_stmt.Close() - _ = socialgroups_get_member_stmt.Close() - _ = socialgroups_get_group_stmt.Close() - _ = socialgroups_create_group_stmt.Close() - _ = socialgroups_attach_forum_stmt.Close() - _ = socialgroups_unattach_forum_stmt.Close() - _ = socialgroups_add_member_stmt.Close() + _ = socialgroupsListStmt.Close() + _ = socialgroupsMemberListStmt.Close() + _ = socialgroupsMemberListJoinStmt.Close() + _ = socialgroupsGetMemberStmt.Close() + _ = socialgroupsGetGroupStmt.Close() + _ = socialgroupsCreateGroupStmt.Close() + _ = socialgroupsAttachForumStmt.Close() + _ = socialgroupsUnattachForumStmt.Close() + _ = socialgroupsAddMemberStmt.Close() } // TO-DO: Stop accessing the query builder directly and add a feature in Gosora which is more easily reversed, if an error comes up during the installation process -func install_socialgroups() error { - sg_table_stmt, err := qgen.Builder.CreateTable("socialgroups","utf8mb4","utf8mb4_general_ci", +func installSocialgroups() error { + sgTableStmt, err := qgen.Builder.CreateTable("socialgroups", "utf8mb4", "utf8mb4_general_ci", []qgen.DB_Table_Column{ - qgen.DB_Table_Column{"sgid","int",0,false,true,""}, - qgen.DB_Table_Column{"name","varchar",100,false,false,""}, - qgen.DB_Table_Column{"desc","varchar",200,false,false,""}, - qgen.DB_Table_Column{"active","boolean",1,false,false,""}, - qgen.DB_Table_Column{"privacy","smallint",0,false,false,""}, - qgen.DB_Table_Column{"joinable","smallint",0,false,false,"0"}, - qgen.DB_Table_Column{"owner","int",0,false,false,""}, - qgen.DB_Table_Column{"memberCount","int",0,false,false,""}, - qgen.DB_Table_Column{"mainForum","int",0,false,false,"0"}, // The board the user lands on when they click on a group, we'll make it possible for group admins to change what users land on + qgen.DB_Table_Column{"sgid", "int", 0, false, true, ""}, + qgen.DB_Table_Column{"name", "varchar", 100, false, false, ""}, + qgen.DB_Table_Column{"desc", "varchar", 200, false, false, ""}, + qgen.DB_Table_Column{"active", "boolean", 1, false, false, ""}, + qgen.DB_Table_Column{"privacy", "smallint", 0, false, false, ""}, + qgen.DB_Table_Column{"joinable", "smallint", 0, false, false, "0"}, + qgen.DB_Table_Column{"owner", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"memberCount", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"mainForum", "int", 0, false, false, "0"}, // The board the user lands on when they click on a group, we'll make it possible for group admins to change what users land on //qgen.DB_Table_Column{"boards","varchar",255,false,false,""}, // Cap the max number of boards at 8 to avoid overflowing the confines of a 64-bit integer? - qgen.DB_Table_Column{"backdrop","varchar",200,false,false,""}, // File extension for the uploaded file, or an external link - qgen.DB_Table_Column{"createdAt","createdAt",0,false,false,""}, - qgen.DB_Table_Column{"lastUpdateTime","datetime",0,false,false,""}, + qgen.DB_Table_Column{"backdrop", "varchar", 200, false, false, ""}, // File extension for the uploaded file, or an external link + qgen.DB_Table_Column{"createdAt", "createdAt", 0, false, false, ""}, + qgen.DB_Table_Column{"lastUpdateTime", "datetime", 0, false, false, ""}, }, []qgen.DB_Table_Key{ - qgen.DB_Table_Key{"sgid","primary"}, + qgen.DB_Table_Key{"sgid", "primary"}, }, ) if err != nil { return err } - _, err = sg_table_stmt.Exec() + _, err = sgTableStmt.Exec() if err != nil { return err } - sg_members_table_stmt, err := qgen.Builder.CreateTable("socialgroups_members","","", + sgMembersTableStmt, err := qgen.Builder.CreateTable("socialgroups_members", "", "", []qgen.DB_Table_Column{ - qgen.DB_Table_Column{"sgid","int",0,false,false,""}, - qgen.DB_Table_Column{"uid","int",0,false,false,""}, - qgen.DB_Table_Column{"rank","int",0,false,false,"0"}, /* 0: Member. 1: Mod. 2: Admin. */ - qgen.DB_Table_Column{"posts","int",0,false,false,"0"}, /* Per-Group post count. Should we do some sort of score system? */ - qgen.DB_Table_Column{"joinedAt","datetime",0,false,false,""}, + qgen.DB_Table_Column{"sgid", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"uid", "int", 0, false, false, ""}, + qgen.DB_Table_Column{"rank", "int", 0, false, false, "0"}, /* 0: Member. 1: Mod. 2: Admin. */ + qgen.DB_Table_Column{"posts", "int", 0, false, false, "0"}, /* Per-Group post count. Should we do some sort of score system? */ + qgen.DB_Table_Column{"joinedAt", "datetime", 0, false, false, ""}, }, []qgen.DB_Table_Key{}, ) - if err != nil { - return err - } + if err != nil { + return err + } - _, err = sg_members_table_stmt.Exec() - return err + _, err = sgMembersTableStmt.Exec() + return err } // TO-DO; Implement an uninstallation system into Gosora. And a better installation system. -func uninstall_socialgroups() error { +func uninstallSocialgroups() error { return nil } // TO-DO: Do this properly via the widget system -func socialgroups_common_area_widgets(headerVars *HeaderVars) { +func socialgroupsCommonAreaWidgets(headerVars *HeaderVars) { // TO-DO: Hot Groups? Featured Groups? Official Groups? var b bytes.Buffer - var menu WidgetMenu = WidgetMenu{"Social Groups",[]WidgetMenuItem{ - WidgetMenuItem{"Create Group","/group/create/",false}, + var menu = WidgetMenu{"Social Groups", []WidgetMenuItem{ + WidgetMenuItem{"Create Group", "/group/create/", false}, }} - err := templates.ExecuteTemplate(&b,"widget_menu.html",menu) + err := templates.ExecuteTemplate(&b, "widget_menu.html", menu) if err != nil { LogError(err) return @@ -255,16 +252,16 @@ func socialgroups_common_area_widgets(headerVars *HeaderVars) { // TO-DO: Do this properly via the widget system // TO-DO: Make a better more customisable group widget system -func socialgroups_group_widgets(headerVars *HeaderVars, sgItem SocialGroup) (success bool) { +func socialgroupsGroupWidgets(headerVars *HeaderVars, sgItem *SocialGroup) (success bool) { return false // Disabled until the next commit - var b bytes.Buffer - var menu WidgetMenu = WidgetMenu{"Group Options",[]WidgetMenuItem{ - WidgetMenuItem{"Join","/group/join/" + strconv.Itoa(sgItem.ID),false}, - WidgetMenuItem{"Members","/group/members/" + strconv.Itoa(sgItem.ID),false}, + /*var b bytes.Buffer + var menu WidgetMenu = WidgetMenu{"Group Options", []WidgetMenuItem{ + WidgetMenuItem{"Join", "/group/join/" + strconv.Itoa(sgItem.ID), false}, + WidgetMenuItem{"Members", "/group/members/" + strconv.Itoa(sgItem.ID), false}, }} - err := templates.ExecuteTemplate(&b,"widget_menu.html",menu) + err := templates.ExecuteTemplate(&b, "widget_menu.html", menu) if err != nil { LogError(err) return false @@ -277,249 +274,256 @@ func socialgroups_group_widgets(headerVars *HeaderVars, sgItem SocialGroup) (suc } else { return false } - return true + return true*/ } /* Custom Pages */ -func socialgroups_group_list(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) +func socialgroupsGroupList(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } - socialgroups_common_area_widgets(&headerVars) + socialgroupsCommonAreaWidgets(headerVars) - rows, err := socialgroups_list_stmt.Query() - if err != nil && err != ErrNoRows { - InternalError(err,w) + rows, err := socialgroupsListStmt.Query() + if err != nil && err != ErrNoRows { + InternalError(err, w) return } - var sgList []SocialGroup + var sgList []*SocialGroup for rows.Next() { - sgItem := SocialGroup{ID:0} + sgItem := &SocialGroup{ID: 0} err := rows.Scan(&sgItem.ID, &sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &sgItem.CreatedAt, &sgItem.LastUpdateTime) - if err != nil { - InternalError(err,w) - return - } - sgItem.Link = socialgroups_build_group_url(name_to_slug(sgItem.Name),sgItem.ID) - sgList = append(sgList,sgItem) - } - err = rows.Err() - if err != nil { - InternalError(err,w) - return - } - rows.Close() - - pi := SocialGroupListPage{"Group List",user,headerVars,sgList,extData} - err = templates.ExecuteTemplate(w,"socialgroups_group_list.html", pi) + if err != nil { + InternalError(err, w) + return + } + sgItem.Link = socialgroupsBuildGroupURL(nameToSlug(sgItem.Name), sgItem.ID) + sgList = append(sgList, sgItem) + } + err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) + return + } + rows.Close() + + pi := SocialGroupListPage{"Group List", user, headerVars, sgList} + err = templates.ExecuteTemplate(w, "socialgroups_group_list.html", pi) + if err != nil { + InternalError(err, w) } } -func socialgroups_get_group(sgid int) (sgItem SocialGroup, err error) { - sgItem = SocialGroup{ID:sgid} - err = socialgroups_get_group_stmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &sgItem.MainForumID, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime) +func socialgroupsGetGroup(sgid int) (sgItem *SocialGroup, err error) { + sgItem = &SocialGroup{ID: sgid} + err = socialgroupsGetGroupStmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &sgItem.MainForumID, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime) return sgItem, err } -func socialgroups_view_group(w http.ResponseWriter, r *http.Request, user User) { +func socialgroupsViewGroup(w http.ResponseWriter, r *http.Request, user User) { // SEO URLs... - halves := strings.Split(r.URL.Path[len("/group/"):],".") + halves := strings.Split(r.URL.Path[len("/group/"):], ".") if len(halves) < 2 { - halves = append(halves,halves[0]) + halves = append(halves, halves[0]) } sgid, err := strconv.Atoi(halves[1]) if err != nil { - PreError("Not a valid group ID",w,r) + PreError("Not a valid group ID", w, r) return } - sgItem, err := socialgroups_get_group(sgid) + sgItem, err := socialgroupsGetGroup(sgid) if err != nil { - LocalError("Bad group",w,r,user) + LocalError("Bad group", w, r, user) return } if !sgItem.Active { - NotFound(w,r) + NotFound(w, r) } // Re-route the request to route_forums - var ctx context.Context = context.WithValue(r.Context(),"socialgroups_current_group",sgItem) - route_forum(w,r.WithContext(ctx),user,strconv.Itoa(sgItem.MainForumID)) + var ctx = context.WithValue(r.Context(), "socialgroups_current_group", sgItem) + route_forum(w, r.WithContext(ctx), user, strconv.Itoa(sgItem.MainForumID)) } -func socialgroups_create_group(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) +func socialgroupsCreateGroup(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } // TO-DO: Add an approval queue mode for group creation if !user.Loggedin || !user.PluginPerms["CreateSocialGroup"] { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } - socialgroups_common_area_widgets(&headerVars) + socialgroupsCommonAreaWidgets(headerVars) - pi := Page{"Create Group",user,headerVars,tList,nil} - err := templates.ExecuteTemplate(w,"socialgroups_create_group.html", pi) + pi := Page{"Create Group", user, headerVars, tList, nil} + err := templates.ExecuteTemplate(w, "socialgroups_create_group.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func socialgroups_create_group_submit(w http.ResponseWriter, r *http.Request, user User) { +func socialgroupsCreateGroupSubmit(w http.ResponseWriter, r *http.Request, user User) { // TO-DO: Add an approval queue mode for group creation if !user.Loggedin || !user.PluginPerms["CreateSocialGroup"] { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } - var group_active bool = true - var group_name string = html.EscapeString(r.PostFormValue("group_name")) - var group_desc string = html.EscapeString(r.PostFormValue("group_desc")) - var gprivacy string = r.PostFormValue("group_privacy") + var groupActive = true + var groupName = html.EscapeString(r.PostFormValue("group_name")) + var groupDesc = html.EscapeString(r.PostFormValue("group_desc")) + var gprivacy = r.PostFormValue("group_privacy") - var group_privacy int - switch(gprivacy) { - case "0": group_privacy = 0 // Public - case "1": group_privacy = 1 // Protected - case "2": group_privacy = 2 // private - default: group_privacy = 0 + var groupPrivacy int + switch gprivacy { + case "0": + groupPrivacy = 0 // Public + case "1": + groupPrivacy = 1 // Protected + case "2": + groupPrivacy = 2 // private + default: + groupPrivacy = 0 } // Create the backing forum - fid, err := fstore.CreateForum(group_name,"",true,"") + fid, err := fstore.CreateForum(groupName, "", true, "") if err != nil { - InternalError(err,w) + InternalError(err, w) return } - res, err := socialgroups_create_group_stmt.Exec(group_name, group_desc, group_active, group_privacy, user.ID, fid) + res, err := socialgroupsCreateGroupStmt.Exec(groupName, groupDesc, groupActive, groupPrivacy, user.ID, fid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - lastId, err := res.LastInsertId() + lastID, err := res.LastInsertId() if err != nil { - InternalError(err,w) + InternalError(err, w) return } // Add the main backing forum to the forum list - err = socialgroups_attach_forum(int(lastId),fid) + err = socialgroupsAttachForum(int(lastID), fid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = socialgroups_add_member_stmt.Exec(lastId,user.ID,2) + _, err = socialgroupsAddMemberStmt.Exec(lastID, user.ID, 2) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,socialgroups_build_group_url(name_to_slug(group_name),int(lastId)), http.StatusSeeOther) + http.Redirect(w, r, socialgroupsBuildGroupURL(nameToSlug(groupName), int(lastID)), http.StatusSeeOther) } -func socialgroups_member_list(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) +func socialgroupsMemberList(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } // SEO URLs... - halves := strings.Split(r.URL.Path[len("/group/members/"):],".") + halves := strings.Split(r.URL.Path[len("/group/members/"):], ".") if len(halves) < 2 { - halves = append(halves,halves[0]) + halves = append(halves, halves[0]) } sgid, err := strconv.Atoi(halves[1]) if err != nil { - PreError("Not a valid group ID",w,r) + PreError("Not a valid group ID", w, r) return } - var sgItem SocialGroup = SocialGroup{ID:sgid} + var sgItem = &SocialGroup{ID: sgid} var mainForum int // Unused - err = socialgroups_get_group_stmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &mainForum, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime) + err = socialgroupsGetGroupStmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &mainForum, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime) if err != nil { - LocalError("Bad group",w,r,user) + LocalError("Bad group", w, r, user) return } - sgItem.Link = socialgroups_build_group_url(name_to_slug(sgItem.Name),sgItem.ID) + sgItem.Link = socialgroupsBuildGroupURL(nameToSlug(sgItem.Name), sgItem.ID) - socialgroups_group_widgets(&headerVars, sgItem) + socialgroupsGroupWidgets(headerVars, sgItem) - rows, err := socialgroups_member_list_join_stmt.Query(sgid) - if err != nil && err != ErrNoRows { - InternalError(err,w) + rows, err := socialgroupsMemberListJoinStmt.Query(sgid) + if err != nil && err != ErrNoRows { + InternalError(err, w) return } var sgMembers []SocialGroupMember for rows.Next() { - sgMember := SocialGroupMember{PostCount:0} - err := rows.Scan(&sgMember.User.ID,&sgMember.Rank,&sgMember.PostCount,&sgMember.JoinedAt,&sgMember.User.Name, &sgMember.User.Avatar) - if err != nil { - InternalError(err,w) - return - } - sgMember.Link = build_profile_url(name_to_slug(sgMember.User.Name),sgMember.User.ID) + sgMember := SocialGroupMember{PostCount: 0} + err := rows.Scan(&sgMember.User.ID, &sgMember.Rank, &sgMember.PostCount, &sgMember.JoinedAt, &sgMember.User.Name, &sgMember.User.Avatar) + if err != nil { + InternalError(err, w) + return + } + sgMember.Link = buildProfileURL(nameToSlug(sgMember.User.Name), sgMember.User.ID) if sgMember.User.Avatar != "" { if sgMember.User.Avatar[0] == '.' { sgMember.User.Avatar = "/uploads/avatar_" + strconv.Itoa(sgMember.User.ID) + sgMember.User.Avatar } } else { - sgMember.User.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(sgMember.User.ID),1) + sgMember.User.Avatar = strings.Replace(config.Noavatar, "{id}", strconv.Itoa(sgMember.User.ID), 1) } - sgMember.JoinedAt, _ = relative_time(sgMember.JoinedAt) + sgMember.JoinedAt, _ = relativeTime(sgMember.JoinedAt) if sgItem.Owner == sgMember.User.ID { sgMember.RankString = "Owner" } else { - switch(sgMember.Rank) { - case 0: sgMember.RankString = "Member" - case 1: sgMember.RankString = "Mod" - case 2: sgMember.RankString = "Admin" + switch sgMember.Rank { + case 0: + sgMember.RankString = "Member" + case 1: + sgMember.RankString = "Mod" + case 2: + sgMember.RankString = "Admin" } } - sgMembers = append(sgMembers,sgMember) - } - err = rows.Err() - if err != nil { - InternalError(err,w) - return - } - rows.Close() + sgMembers = append(sgMembers, sgMember) + } + err = rows.Err() + if err != nil { + InternalError(err, w) + return + } + rows.Close() - pi := SocialGroupMemberListPage{"Group Member List",user,headerVars,sgMembers,sgItem,0,0,extData} + pi := SocialGroupMemberListPage{"Group Member List", user, headerVars, sgMembers, sgItem, 0, 0} // A plugin with plugins. Pluginception! - if pre_render_hooks["pre_render_socialgroups_member_list"] != nil { - if run_pre_render_hook("pre_render_socialgroups_member_list", w, r, &user, &pi) { + if preRenderHooks["pre_render_socialgroups_member_list"] != nil { + if runPreRenderHook("pre_render_socialgroups_member_list", w, r, &user, &pi) { return } } - err = templates.ExecuteTemplate(w,"socialgroups_member_list.html", pi) + err = templates.ExecuteTemplate(w, "socialgroups_member_list.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func socialgroups_attach_forum(sgid int, fid int) error { - _, err := socialgroups_attach_forum_stmt.Exec(sgid,fid) +func socialgroupsAttachForum(sgid int, fid int) error { + _, err := socialgroupsAttachForumStmt.Exec(sgid, fid) return err } -func socialgroups_unattach_forum(fid int) error { - _, err := socialgroups_attach_forum_stmt.Exec(fid) +func socialgroupsUnattachForum(fid int) error { + _, err := socialgroupsAttachForumStmt.Exec(fid) return err } -func socialgroups_build_group_url(slug string, id int) string { +func socialgroupsBuildGroupURL(slug string, id int) string { if slug == "" { return "/group/" + slug + "." + strconv.Itoa(id) } @@ -530,38 +534,38 @@ func socialgroups_build_group_url(slug string, id int) string { Hooks */ -func socialgroups_pre_render_view_forum(w http.ResponseWriter, r *http.Request, user *User, data interface{}) (halt bool) { +func socialgroupsPreRenderViewForum(w http.ResponseWriter, r *http.Request, user *User, data interface{}) (halt bool) { pi := data.(*ForumPage) if pi.Header.ExtData.items != nil { - if sgData, ok := pi.Header.ExtData.items["socialgroups_current_group"]; ok { - sgItem := sgData.(SocialGroup) + if sgData, ok := pi.Header.ExtData.items["socialgroups_current_group"]; ok { + sgItem := sgData.(*SocialGroup) - sgpi := SocialGroupPage{pi.Title,pi.CurrentUser,pi.Header,pi.ItemList,pi.Forum,sgItem,pi.Page,pi.LastPage,pi.ExtData} - err := templates.ExecuteTemplate(w,"socialgroups_view_group.html", sgpi) + sgpi := SocialGroupPage{pi.Title, pi.CurrentUser, pi.Header, pi.ItemList, pi.Forum, sgItem, pi.Page, pi.LastPage} + err := templates.ExecuteTemplate(w, "socialgroups_view_group.html", sgpi) if err != nil { LogError(err) return false } return true - } + } } return false } -func socialgroups_trow_assign(args ...interface{}) interface{} { - var forum *Forum = args[1].(*Forum) +func socialgroupsTrowAssign(args ...interface{}) interface{} { + var forum = args[1].(*Forum) if forum.ParentType == "socialgroup" { - var topicItem *TopicsRow = args[0].(*TopicsRow) - topicItem.ForumLink = "/group/" + strings.TrimPrefix(topicItem.ForumLink,get_forum_url_prefix()) + var topicItem = args[0].(*TopicsRow) + topicItem.ForumLink = "/group/" + strings.TrimPrefix(topicItem.ForumLink, getForumURLPrefix()) } return nil } // TO-DO: It would be nice, if you could select one of the boards in the group from that drop-down rather than just the one you got linked from -func socialgroups_topic_create_pre_loop(args ...interface{}) interface{} { - var fid int = args[2].(int) +func socialgroupsTopicCreatePreLoop(args ...interface{}) interface{} { + var fid = args[2].(int) if fstore.DirtyGet(fid).ParentType == "socialgroup" { - var strictmode *bool = args[5].(*bool) + var strictmode = args[5].(*bool) *strictmode = true } return nil @@ -569,33 +573,33 @@ func socialgroups_topic_create_pre_loop(args ...interface{}) interface{} { // TO-DO: Add privacy options // TO-DO: Add support for multiple boards and add per-board simplified permissions -// TO-DO: Take is_js into account for routes which expect JSON responses -func socialgroups_forum_check(args ...interface{}) (skip interface{}) { +// TO-DO: Take isJs into account for routes which expect JSON responses +func socialgroupsForumCheck(args ...interface{}) (skip interface{}) { var r = args[1].(*http.Request) - var fid *int = args[3].(*int) - var forum *Forum = fstore.DirtyGet(*fid) + var fid = args[3].(*int) + var forum = fstore.DirtyGet(*fid) if forum.ParentType == "socialgroup" { var err error var w = args[0].(http.ResponseWriter) - var success *bool = args[4].(*bool) - sgItem, ok := r.Context().Value("socialgroups_current_group").(SocialGroup) + var success = args[4].(*bool) + sgItem, ok := r.Context().Value("socialgroups_current_group").(*SocialGroup) if !ok { - sgItem, err = socialgroups_get_group(forum.ParentID) + sgItem, err = socialgroupsGetGroup(forum.ParentID) if err != nil { - InternalError(errors.New("Unable to find the parent group for a forum"),w) + InternalError(errors.New("Unable to find the parent group for a forum"), w) *success = false return false } if !sgItem.Active { - NotFound(w,r) + NotFound(w, r) *success = false return false } - r = r.WithContext(context.WithValue(r.Context(),"socialgroups_current_group",sgItem)) + r = r.WithContext(context.WithValue(r.Context(), "socialgroups_current_group", sgItem)) } - var user *User = args[2].(*User) + var user = args[2].(*User) var rank int var posts int var joinedAt string @@ -604,13 +608,13 @@ func socialgroups_forum_check(args ...interface{}) (skip interface{}) { // Clear the default group permissions // TO-DO: Do this more efficiently, doing it quick and dirty for now to get this out quickly - override_forum_perms(&user.Perms, false) + overrideForumPerms(&user.Perms, false) user.Perms.ViewTopic = true - err = socialgroups_get_member_stmt.QueryRow(sgItem.ID,user.ID).Scan(&rank,&posts,&joinedAt) + err = socialgroupsGetMemberStmt.QueryRow(sgItem.ID, user.ID).Scan(&rank, &posts, &joinedAt) if err != nil && err != ErrNoRows { *success = false - InternalError(err,w) + InternalError(err, w) return false } else if err != nil { return true @@ -623,13 +627,13 @@ func socialgroups_forum_check(args ...interface{}) (skip interface{}) { // Basic permissions for members, more complicated permissions coming in the next commit! if sgItem.Owner == user.ID { - override_forum_perms(&user.Perms,true) + overrideForumPerms(&user.Perms, true) } else if rank == 0 { user.Perms.LikeItem = true user.Perms.CreateTopic = true user.Perms.CreateReply = true } else { - override_forum_perms(&user.Perms,true) + overrideForumPerms(&user.Perms, true) } return true } @@ -639,19 +643,19 @@ func socialgroups_forum_check(args ...interface{}) (skip interface{}) { // TO-DO: Override redirects? I don't think this is needed quite yet -func socialgroups_widgets(args ...interface{}) interface{} { - var zone string = args[0].(string) - var headerVars *HeaderVars = args[2].(*HeaderVars) - var request *http.Request = args[3].(*http.Request) +func socialgroupsWidgets(args ...interface{}) interface{} { + var zone = args[0].(string) + var headerVars = args[2].(*HeaderVars) + var request = args[3].(*http.Request) if zone != "view_forum" { return false } - var forum *Forum = args[1].(*Forum) + var forum = args[1].(*Forum) if forum.ParentType == "socialgroup" { // This is why I hate using contexts, all the daisy chains and interface casts x.x - sgItem, ok := request.Context().Value("socialgroups_current_group").(SocialGroup) + sgItem, ok := request.Context().Value("socialgroups_current_group").(*SocialGroup) if !ok { LogError(errors.New("Unable to find a parent group in the context data")) return false @@ -662,7 +666,7 @@ func socialgroups_widgets(args ...interface{}) interface{} { } headerVars.ExtData.items["socialgroups_current_group"] = sgItem - return socialgroups_group_widgets(headerVars,sgItem) + return socialgroupsGroupWidgets(headerVars, sgItem) } return false } diff --git a/plugin_test.go b/plugin_test.go index c19e5323..1e76db61 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -6,226 +6,225 @@ import "testing" // TO-DO: Replace the soft tabs with hard ones // go test -v -type ME_Pair struct -{ - Msg string - Expects string +type ME_Pair struct { + Msg string + Expects string } func addMEPair(msgList []ME_Pair, msg string, expects string) []ME_Pair { - return append(msgList,ME_Pair{msg,expects}) + return append(msgList, ME_Pair{msg, expects}) } func TestBBCodeRender(t *testing.T) { - //t.Skip() - var res string - var msgList []ME_Pair - msgList = addMEPair(msgList,"hi","hi") - msgList = addMEPair(msgList,"😀","😀") - msgList = addMEPair(msgList,"[b]😀[/b]","😀") - msgList = addMEPair(msgList,"[b]😀😀😀[/b]","😀😀😀") - msgList = addMEPair(msgList,"[b]hi[/b]","hi") - msgList = addMEPair(msgList,"[u]hi[/u]","hi") - msgList = addMEPair(msgList,"[i]hi[/i]","hi") - msgList = addMEPair(msgList,"[s]hi[/s]","hi") - msgList = addMEPair(msgList,"[c]hi[/c]","[c]hi[/c]") - if !testing.Short() { - msgList = addMEPair(msgList,"[b]hi[/i]","[b]hi[/i]") - msgList = addMEPair(msgList,"[/b]hi[b]","[/b]hi[b]") - msgList = addMEPair(msgList,"[/b]hi[/b]","[/b]hi[/b]") - msgList = addMEPair(msgList,"[b][b]hi[/b]","hi") - } - msgList = addMEPair(msgList,"[b][b]hi","[b][b]hi") - msgList = addMEPair(msgList,"[b][b][b]hi","[b][b][b]hi") - msgList = addMEPair(msgList,"[/b]hi","[/b]hi") - msgList = addMEPair(msgList,"[code]hi[/code]","hi") - msgList = addMEPair(msgList,"[code][b]hi[/b][/code]","[b]hi[/b]") - msgList = addMEPair(msgList,"[code][b]hi[/code][/b]","[b]hi[/b]") - msgList = addMEPair(msgList,"[quote]hi[/quote]","hi") - msgList = addMEPair(msgList,"[quote][b]hi[/b][/quote]","hi") - msgList = addMEPair(msgList,"[quote][b]h[/b][/quote]","h") - msgList = addMEPair(msgList,"[quote][b][/b][/quote]","") + //t.Skip() + var res string + var msgList []ME_Pair + msgList = addMEPair(msgList, "hi", "hi") + msgList = addMEPair(msgList, "😀", "😀") + msgList = addMEPair(msgList, "[b]😀[/b]", "😀") + msgList = addMEPair(msgList, "[b]😀😀😀[/b]", "😀😀😀") + msgList = addMEPair(msgList, "[b]hi[/b]", "hi") + msgList = addMEPair(msgList, "[u]hi[/u]", "hi") + msgList = addMEPair(msgList, "[i]hi[/i]", "hi") + msgList = addMEPair(msgList, "[s]hi[/s]", "hi") + msgList = addMEPair(msgList, "[c]hi[/c]", "[c]hi[/c]") + if !testing.Short() { + msgList = addMEPair(msgList, "[b]hi[/i]", "[b]hi[/i]") + msgList = addMEPair(msgList, "[/b]hi[b]", "[/b]hi[b]") + msgList = addMEPair(msgList, "[/b]hi[/b]", "[/b]hi[/b]") + msgList = addMEPair(msgList, "[b][b]hi[/b]", "hi") + } + msgList = addMEPair(msgList, "[b][b]hi", "[b][b]hi") + msgList = addMEPair(msgList, "[b][b][b]hi", "[b][b][b]hi") + msgList = addMEPair(msgList, "[/b]hi", "[/b]hi") + msgList = addMEPair(msgList, "[code]hi[/code]", "hi") + msgList = addMEPair(msgList, "[code][b]hi[/b][/code]", "[b]hi[/b]") + msgList = addMEPair(msgList, "[code][b]hi[/code][/b]", "[b]hi[/b]") + msgList = addMEPair(msgList, "[quote]hi[/quote]", "hi") + msgList = addMEPair(msgList, "[quote][b]hi[/b][/quote]", "hi") + msgList = addMEPair(msgList, "[quote][b]h[/b][/quote]", "h") + msgList = addMEPair(msgList, "[quote][b][/b][/quote]", "") - t.Log("Testing bbcode_full_parse") - for _, item := range msgList { - t.Log("Testing string '"+item.Msg+"'") - res = bbcode_full_parse(item.Msg) - if res != item.Expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",item.Expects) - } - } + t.Log("Testing bbcodeFullParse") + for _, item := range msgList { + t.Log("Testing string '" + item.Msg + "'") + res = bbcodeFullParse(item.Msg) + if res != item.Expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", item.Expects) + } + } - var msg, expects string - var err error + var msg, expects string + var err error - msg = "[rand][/rand]" - expects = "[Invalid Number][rand][/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - if res != expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",expects) - } + msg = "[rand][/rand]" + expects = "[Invalid Number][rand][/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + if res != expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", expects) + } - msg = "[rand]-1[/rand]" - expects = "[No Negative Numbers][rand]-1[/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - if res != expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",expects) - } + msg = "[rand]-1[/rand]" + expects = "[No Negative Numbers][rand]-1[/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + if res != expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", expects) + } - msg = "[rand]-01[/rand]" - expects = "[No Negative Numbers][rand]-01[/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - if res != expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",expects) - } + msg = "[rand]-01[/rand]" + expects = "[No Negative Numbers][rand]-01[/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + if res != expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", expects) + } - msg = "[rand]NaN[/rand]" - expects = "[Invalid Number][rand]NaN[/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - if res != expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",expects) - } + msg = "[rand]NaN[/rand]" + expects = "[Invalid Number][rand]NaN[/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + if res != expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", expects) + } - msg = "[rand]Inf[/rand]" - expects = "[Invalid Number][rand]Inf[/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - if res != expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",expects) - } + msg = "[rand]Inf[/rand]" + expects = "[Invalid Number][rand]Inf[/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + if res != expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", expects) + } - msg = "[rand]+[/rand]" - expects = "[Invalid Number][rand]+[/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - if res != expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",expects) - } + msg = "[rand]+[/rand]" + expects = "[Invalid Number][rand]+[/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + if res != expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", expects) + } - msg = "[rand]1+1[/rand]" - expects = "[Invalid Number][rand]1+1[/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - if res != expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",expects) - } + msg = "[rand]1+1[/rand]" + expects = "[Invalid Number][rand]1+1[/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + if res != expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", expects) + } - var conv int - msg = "[rand]1[/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - conv, err = strconv.Atoi(res) - if err != nil || (conv > 1 || conv < 0) { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected a number in the range 0-1") - } + var conv int + msg = "[rand]1[/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + conv, err = strconv.Atoi(res) + if err != nil || (conv > 1 || conv < 0) { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected a number in the range 0-1") + } - msg = "[rand]0[/rand]" - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - conv, err = strconv.Atoi(res) - if err != nil || conv != 0 { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected the number 0") - } + msg = "[rand]0[/rand]" + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + conv, err = strconv.Atoi(res) + if err != nil || conv != 0 { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected the number 0") + } - msg = "[rand]2147483647[/rand]" // Signed 32-bit MAX - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - conv, err = strconv.Atoi(res) - if err != nil || (conv > 2147483647 || conv < 0) { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected a number between 0 and 2147483647") - } + msg = "[rand]2147483647[/rand]" // Signed 32-bit MAX + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + conv, err = strconv.Atoi(res) + if err != nil || (conv > 2147483647 || conv < 0) { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected a number between 0 and 2147483647") + } - msg = "[rand]9223372036854775807[/rand]" // Signed 64-bit MAX - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - conv, err = strconv.Atoi(res) - if err != nil || (conv > 9223372036854775807 || conv < 0) { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected a number between 0 and 9223372036854775807") - } + msg = "[rand]9223372036854775807[/rand]" // Signed 64-bit MAX + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + conv, err = strconv.Atoi(res) + if err != nil || (conv > 9223372036854775807 || conv < 0) { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected a number between 0 and 9223372036854775807") + } - // Note: conv is commented out in these two, as these numbers overflow int - msg = "[rand]18446744073709551615[/rand]" // Unsigned 64-bit MAX - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - conv, err = strconv.Atoi(res) - if err != nil || (/*conv > 18446744073709551615 || */conv < 0) { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected a number between 0 and 18446744073709551615") - } - msg = "[rand]170141183460469231731687303715884105727[/rand]" // Signed 128-bit MAX - t.Log("Testing string '"+msg+"'") - res = bbcode_full_parse(msg) - conv, err = strconv.Atoi(res) - if err != nil || (/*conv > 170141183460469231731687303715884105727 || */conv < 0) { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected a number between 0 and 170141183460469231731687303715884105727") - } + // Note: conv is commented out in these two, as these numbers overflow int + msg = "[rand]18446744073709551615[/rand]" // Unsigned 64-bit MAX + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + conv, err = strconv.Atoi(res) + if err != nil || ( /*conv > 18446744073709551615 || */ conv < 0) { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected a number between 0 and 18446744073709551615") + } + msg = "[rand]170141183460469231731687303715884105727[/rand]" // Signed 128-bit MAX + t.Log("Testing string '" + msg + "'") + res = bbcodeFullParse(msg) + conv, err = strconv.Atoi(res) + if err != nil || ( /*conv > 170141183460469231731687303715884105727 || */ conv < 0) { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected a number between 0 and 170141183460469231731687303715884105727") + } - t.Log("Testing bbcode_regex_parse") - for _, item := range msgList { - t.Log("Testing string '"+item.Msg+"'") - res = bbcode_regex_parse(item.Msg) - if res != item.Expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",item.Expects) - } - } + t.Log("Testing bbcode_regex_parse") + for _, item := range msgList { + t.Log("Testing string '" + item.Msg + "'") + res = bbcodeRegexParse(item.Msg) + if res != item.Expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", item.Expects) + } + } } func TestMarkdownRender(t *testing.T) { - //t.Skip() - var res string - var msgList []ME_Pair - msgList = addMEPair(msgList,"hi","hi") - msgList = addMEPair(msgList,"**hi**","hi") - msgList = addMEPair(msgList,"_hi_","hi") - msgList = addMEPair(msgList,"*hi*","hi") - msgList = addMEPair(msgList,"~hi~","hi") - msgList = addMEPair(msgList,"*hi**","hi*") - msgList = addMEPair(msgList,"**hi***","hi*") - msgList = addMEPair(msgList,"**hi*","*hi") - msgList = addMEPair(msgList,"***hi***","*hi") - msgList = addMEPair(msgList,"\\*hi\\*","*hi*") - msgList = addMEPair(msgList,"*~hi~*","hi") - msgList = addMEPair(msgList,"**","**") - msgList = addMEPair(msgList,"***","***") - msgList = addMEPair(msgList,"****","****") - msgList = addMEPair(msgList,"*****","*****") - msgList = addMEPair(msgList,"******","******") - msgList = addMEPair(msgList,"*******","*******") - msgList = addMEPair(msgList,"~~","~~") - msgList = addMEPair(msgList,"~~~","~~~") - msgList = addMEPair(msgList,"~~~~","~~~~") - msgList = addMEPair(msgList,"~~~~~","~~~~~") - msgList = addMEPair(msgList,"__","__") - msgList = addMEPair(msgList,"___","___") - msgList = addMEPair(msgList,"_ _"," ") - msgList = addMEPair(msgList,"* *"," ") - msgList = addMEPair(msgList,"** **"," ") - msgList = addMEPair(msgList,"*** ***"," ") + //t.Skip() + var res string + var msgList []ME_Pair + msgList = addMEPair(msgList, "hi", "hi") + msgList = addMEPair(msgList, "**hi**", "hi") + msgList = addMEPair(msgList, "_hi_", "hi") + msgList = addMEPair(msgList, "*hi*", "hi") + msgList = addMEPair(msgList, "~hi~", "hi") + msgList = addMEPair(msgList, "*hi**", "hi*") + msgList = addMEPair(msgList, "**hi***", "hi*") + msgList = addMEPair(msgList, "**hi*", "*hi") + msgList = addMEPair(msgList, "***hi***", "*hi") + msgList = addMEPair(msgList, "\\*hi\\*", "*hi*") + msgList = addMEPair(msgList, "*~hi~*", "hi") + msgList = addMEPair(msgList, "**", "**") + msgList = addMEPair(msgList, "***", "***") + msgList = addMEPair(msgList, "****", "****") + msgList = addMEPair(msgList, "*****", "*****") + msgList = addMEPair(msgList, "******", "******") + msgList = addMEPair(msgList, "*******", "*******") + msgList = addMEPair(msgList, "~~", "~~") + msgList = addMEPair(msgList, "~~~", "~~~") + msgList = addMEPair(msgList, "~~~~", "~~~~") + msgList = addMEPair(msgList, "~~~~~", "~~~~~") + msgList = addMEPair(msgList, "__", "__") + msgList = addMEPair(msgList, "___", "___") + msgList = addMEPair(msgList, "_ _", " ") + msgList = addMEPair(msgList, "* *", " ") + msgList = addMEPair(msgList, "** **", " ") + msgList = addMEPair(msgList, "*** ***", " ") - for _, item := range msgList { - t.Log("Testing string '"+item.Msg+"'") - res = markdown_parse(item.Msg) - if res != item.Expects { - t.Error("Bad output:","'"+res+"'") - t.Error("Expected:",item.Expects) - } - } + for _, item := range msgList { + t.Log("Testing string '" + item.Msg + "'") + res = markdownParse(item.Msg) + if res != item.Expects { + t.Error("Bad output:", "'"+res+"'") + t.Error("Expected:", item.Expects) + } + } } diff --git a/public/global.js b/public/global.js index 1d11e2e8..59dfbc4d 100644 --- a/public/global.js +++ b/public/global.js @@ -250,7 +250,7 @@ $(document).ready(function(){ var form_action = $(this).closest('a').attr("href"); //console.log("Form Action: " + form_action); - $.ajax({ url: form_action, type: "POST", dataType: "json", data: { is_js: "1", edit_item: newContent } + $.ajax({ url: form_action, type: "POST", dataType: "json", data: { isJs: "1", edit_item: newContent } }); }); }); @@ -276,7 +276,7 @@ $(document).ready(function(){ url: form_action + "?session=" + session, type: "POST", dataType: "json", - data: {is_js: "1",edit_item: newContent} + data: {isJs: "1",edit_item: newContent} }); }); }); @@ -325,7 +325,7 @@ $(document).ready(function(){ { event.preventDefault(); //console.log("running .submit_edit event"); - var out_data = {is_js: "1"} + var out_data = {isJs: "1"} var block_parent = $(this).closest('.editable_parent'); var block = block_parent.find('.editable_block').each(function(){ var field_name = this.getAttribute("data-field"); diff --git a/query_gen/lib/install.go b/query_gen/lib/install.go index 6f34be17..befb5d05 100644 --- a/query_gen/lib/install.go +++ b/query_gen/lib/install.go @@ -4,21 +4,19 @@ package qgen var Install *installer func init() { - Install = &installer{instructions:[]DB_Install_Instruction{}} + Install = &installer{instructions: []DB_Install_Instruction{}} } -type DB_Install_Instruction struct -{ - Table string +type DB_Install_Instruction struct { + Table string Contents string - Type string + Type string } // A set of wrappers around the generator methods, so we can use this in the installer // TO-DO: Re-implement the query generation, query builder and installer adapters as layers on-top of a query text adapter -type installer struct -{ - adapter DB_Adapter +type installer struct { + adapter DB_Adapter instructions []DB_Install_Instruction } @@ -40,7 +38,7 @@ func (install *installer) CreateTable(table string, charset string, collation st if err != nil { return err } - install.instructions = append(install.instructions,DB_Install_Instruction{table,res,"create-table"}) + install.instructions = append(install.instructions, DB_Install_Instruction{table, res, "create-table"}) return nil } @@ -49,7 +47,7 @@ func (install *installer) Write() error { // We can't escape backticks, so we have to dump it out a file at a time for _, instr := range install.instructions { if instr.Type == "create-table" { - err := write_file("./schema/" + install.adapter.GetName() + "/query_" + instr.Table + ".sql", instr.Contents) + err := writeFile("./schema/"+install.adapter.GetName()+"/query_"+instr.Table+".sql", instr.Contents) if err != nil { return err } @@ -57,5 +55,5 @@ func (install *installer) Write() error { inserts += instr.Contents + "\n" } } - return write_file("./schema/" + install.adapter.GetName() + "/inserts.sql", inserts) + return writeFile("./schema/"+install.adapter.GetName()+"/inserts.sql", inserts) } diff --git a/query_gen/lib/mysql.go b/query_gen/lib/mysql.go index e3739d73..402ca17b 100644 --- a/query_gen/lib/mysql.go +++ b/query_gen/lib/mysql.go @@ -8,14 +8,13 @@ import "errors" func init() { DB_Registry = append(DB_Registry, - &Mysql_Adapter{Name:"mysql",Buffer:make(map[string]DB_Stmt)}, + &Mysql_Adapter{Name: "mysql", Buffer: make(map[string]DB_Stmt)}, ) } -type Mysql_Adapter struct -{ - Name string - Buffer map[string]DB_Stmt +type Mysql_Adapter struct { + Name string + Buffer map[string]DB_Stmt BufferOrder []string // Map iteration order is random, so we need this to track the order, so we don't get huge diffs every commit } @@ -41,43 +40,43 @@ func (adapter *Mysql_Adapter) CreateTable(name string, table string, charset str if len(columns) == 0 { return "", errors.New("You can't have a table with no columns") } - - var querystr string = "CREATE TABLE `" + table + "` (" + + var querystr = "CREATE TABLE `" + table + "` (" for _, column := range columns { // Make it easier to support Cassandra in the future if column.Type == "createdAt" { column.Type = "datetime" } - + var size string if column.Size > 0 { size = "(" + strconv.Itoa(column.Size) + ")" } - + var end string // TO-DO: Exclude the other variants of text like mediumtext and longtext too if column.Default != "" && column.Type != "text" { end = " DEFAULT " - if adapter.stringy_type(column.Type) && column.Default != "''" { + if adapter.stringyType(column.Type) && column.Default != "''" { end += "'" + column.Default + "'" } else { end += column.Default } } - + if column.Null { end += " null" } else { end += " not null" } - + if column.Auto_Increment { end += " AUTO_INCREMENT" } - - querystr += "\n\t`"+column.Name+"` " + column.Type + size + end + "," + + querystr += "\n\t`" + column.Name + "` " + column.Type + size + end + "," } - + if len(keys) > 0 { for _, key := range keys { querystr += "\n\t" + key.Type @@ -85,22 +84,22 @@ func (adapter *Mysql_Adapter) CreateTable(name string, table string, charset str querystr += " key" } querystr += "(" - for _, column := range strings.Split(key.Columns,",") { + for _, column := range strings.Split(key.Columns, ",") { querystr += "`" + column + "`," } - querystr = querystr[0:len(querystr) - 1] + ")," + querystr = querystr[0:len(querystr)-1] + ")," } } - - querystr = querystr[0:len(querystr) - 1] + "\n)" + + querystr = querystr[0:len(querystr)-1] + "\n)" if charset != "" { querystr += " CHARSET=" + charset } if collation != "" { querystr += " COLLATE " + collation } - - adapter.push_statement(name,"create-table",querystr + ";") + + adapter.pushStatement(name, "create-table", querystr+";") return querystr + ";", nil } @@ -117,9 +116,9 @@ func (adapter *Mysql_Adapter) SimpleInsert(name string, table string, columns st if len(fields) == 0 { return "", errors.New("No input data found for SimpleInsert") } - - var querystr string = "INSERT INTO `" + table + "`(" - + + var querystr = "INSERT INTO `" + table + "`(" + // Escape the column names, just in case we've used a reserved keyword for _, column := range _process_columns(columns) { if column.Type == "function" { @@ -128,17 +127,17 @@ func (adapter *Mysql_Adapter) SimpleInsert(name string, table string, columns st querystr += "`" + column.Left + "`," } } - + // Remove the trailing comma - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + querystr += ") VALUES (" - for _, field := range _process_fields(fields) { + for _, field := range _processFields(fields) { querystr += field.Name + "," } - querystr = querystr[0:len(querystr) - 1] - - adapter.push_statement(name,"insert",querystr + ")") + querystr = querystr[0 : len(querystr)-1] + + adapter.pushStatement(name, "insert", querystr+")") return querystr + ")", nil } @@ -155,9 +154,9 @@ func (adapter *Mysql_Adapter) SimpleReplace(name string, table string, columns s if len(fields) == 0 { return "", errors.New("No input data found for SimpleInsert") } - - var querystr string = "REPLACE INTO `" + table + "`(" - + + var querystr = "REPLACE INTO `" + table + "`(" + // Escape the column names, just in case we've used a reserved keyword for _, column := range _process_columns(columns) { if column.Type == "function" { @@ -167,15 +166,15 @@ func (adapter *Mysql_Adapter) SimpleReplace(name string, table string, columns s } } // Remove the trailing comma - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + querystr += ") VALUES (" - for _, field := range _process_fields(fields) { + for _, field := range _processFields(fields) { querystr += field.Name + "," } - querystr = querystr[0:len(querystr) - 1] - - adapter.push_statement(name,"replace",querystr + ")") + querystr = querystr[0 : len(querystr)-1] + + adapter.pushStatement(name, "replace", querystr+")") return querystr + ")", nil } @@ -189,48 +188,48 @@ func (adapter *Mysql_Adapter) SimpleUpdate(name string, table string, set string if set == "" { return "", errors.New("You need to set data in this update statement") } - - var querystr string = "UPDATE `" + table + "` SET " + + var querystr = "UPDATE `" + table + "` SET " for _, item := range _process_set(set) { querystr += "`" + item.Column + "` =" for _, token := range item.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - querystr += " `" + token.Contents + "`" - case "string": - querystr += " '" + token.Contents + "'" + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" } } querystr += "," } - + // Remove the trailing comma - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + // Add support for BETWEEN x.x if len(where) != 0 { querystr += " WHERE" - for _, loc := range _process_where(where) { + for _, loc := range _processWhere(where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - querystr += " `" + token.Contents + "`" - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - - adapter.push_statement(name,"update",querystr) + + adapter.pushStatement(name, "update", querystr) return querystr, nil } @@ -244,28 +243,28 @@ func (adapter *Mysql_Adapter) SimpleDelete(name string, table string, where stri if where == "" { return "", errors.New("You need to specify what data you want to delete") } - - var querystr string = "DELETE FROM `" + table + "` WHERE" - + + var querystr = "DELETE FROM `" + table + "` WHERE" + // Add support for BETWEEN x.x - for _, loc := range _process_where(where) { + for _, loc := range _processWhere(where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - querystr += " `" + token.Contents + "`" - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - - querystr = strings.TrimSpace(querystr[0:len(querystr) - 4]) - adapter.push_statement(name,"delete",querystr) + + querystr = strings.TrimSpace(querystr[0 : len(querystr)-4]) + adapter.pushStatement(name, "delete", querystr) return querystr, nil } @@ -277,7 +276,7 @@ func (adapter *Mysql_Adapter) Purge(name string, table string) (string, error) { if table == "" { return "", errors.New("You need a name for this table") } - adapter.push_statement(name,"purge","DELETE FROM `" + table + "`") + adapter.pushStatement(name, "purge", "DELETE FROM `"+table+"`") return "DELETE FROM `" + table + "`", nil } @@ -291,56 +290,56 @@ func (adapter *Mysql_Adapter) SimpleSelect(name string, table string, columns st if len(columns) == 0 { return "", errors.New("No columns found for SimpleSelect") } - + // Slice up the user friendly strings into something easier to process - var colslice []string = strings.Split(strings.TrimSpace(columns),",") - - var querystr string = "SELECT " - + var colslice = strings.Split(strings.TrimSpace(columns), ",") + + var querystr = "SELECT " + // Escape the column names, just in case we've used a reserved keyword for _, column := range colslice { querystr += "`" + strings.TrimSpace(column) + "`," } // Remove the trailing comma - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + querystr += " FROM `" + table + "`" - + // Add support for BETWEEN x.x if len(where) != 0 { querystr += " WHERE" - for _, loc := range _process_where(where) { + for _, loc := range _processWhere(where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - querystr += " `" + token.Contents + "`" - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - + if len(orderby) != 0 { querystr += " ORDER BY " for _, column := range _process_orderby(orderby) { querystr += column.Column + " " + strings.ToUpper(column.Order) + "," } - querystr = querystr[0:len(querystr) - 1] + querystr = querystr[0 : len(querystr)-1] } - + if limit != "" { querystr += " LIMIT " + limit } - + querystr = strings.TrimSpace(querystr) - adapter.push_statement(name,"select",querystr) + adapter.pushStatement(name, "select", querystr) return querystr, nil } @@ -360,12 +359,12 @@ func (adapter *Mysql_Adapter) SimpleLeftJoin(name string, table1 string, table2 if len(joiners) == 0 { return "", errors.New("No joiners found for SimpleLeftJoin") } - - var querystr string = "SELECT " - + + var querystr = "SELECT " + for _, column := range _process_columns(columns) { var source, alias string - + // Escape the column names, just in case we've used a reserved keyword if column.Table != "" { source = "`" + column.Table + "`.`" + column.Left + "`" @@ -374,63 +373,63 @@ func (adapter *Mysql_Adapter) SimpleLeftJoin(name string, table1 string, table2 } else { source = "`" + column.Left + "`" } - + if column.Alias != "" { alias = " AS `" + column.Alias + "`" } querystr += source + alias + "," } - + // Remove the trailing comma - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + querystr += " FROM `" + table1 + "` LEFT JOIN `" + table2 + "` ON " - for _, joiner := range _process_joiner(joiners) { + for _, joiner := range _processJoiner(joiners) { querystr += "`" + joiner.LeftTable + "`.`" + joiner.LeftColumn + "` " + joiner.Operator + " `" + joiner.RightTable + "`.`" + joiner.RightColumn + "` AND " } // Remove the trailing AND - querystr = querystr[0:len(querystr) - 4] - + querystr = querystr[0 : len(querystr)-4] + // Add support for BETWEEN x.x if len(where) != 0 { querystr += " WHERE" - for _, loc := range _process_where(where) { + for _, loc := range _processWhere(where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - halves := strings.Split(token.Contents,".") - if len(halves) == 2 { - querystr += " `" + halves[0] + "`.`" + halves[1] + "`" - } else { - querystr += " `" + token.Contents + "`" - } - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + halves := strings.Split(token.Contents, ".") + if len(halves) == 2 { + querystr += " `" + halves[0] + "`.`" + halves[1] + "`" + } else { + querystr += " `" + token.Contents + "`" + } + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - + if len(orderby) != 0 { querystr += " ORDER BY " for _, column := range _process_orderby(orderby) { querystr += column.Column + " " + strings.ToUpper(column.Order) + "," } - querystr = querystr[0:len(querystr) - 1] + querystr = querystr[0 : len(querystr)-1] } - + if limit != "" { querystr += " LIMIT " + limit } - + querystr = strings.TrimSpace(querystr) - adapter.push_statement(name,"select",querystr) + adapter.pushStatement(name, "select", querystr) return querystr, nil } @@ -450,12 +449,12 @@ func (adapter *Mysql_Adapter) SimpleInnerJoin(name string, table1 string, table2 if len(joiners) == 0 { return "", errors.New("No joiners found for SimpleInnerJoin") } - - var querystr string = "SELECT " - + + var querystr = "SELECT " + for _, column := range _process_columns(columns) { var source, alias string - + // Escape the column names, just in case we've used a reserved keyword if column.Table != "" { source = "`" + column.Table + "`.`" + column.Left + "`" @@ -464,71 +463,71 @@ func (adapter *Mysql_Adapter) SimpleInnerJoin(name string, table1 string, table2 } else { source = "`" + column.Left + "`" } - + if column.Alias != "" { alias = " AS `" + column.Alias + "`" } querystr += source + alias + "," } - + // Remove the trailing comma - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + querystr += " FROM `" + table1 + "` INNER JOIN `" + table2 + "` ON " - for _, joiner := range _process_joiner(joiners) { + for _, joiner := range _processJoiner(joiners) { querystr += "`" + joiner.LeftTable + "`.`" + joiner.LeftColumn + "` " + joiner.Operator + " `" + joiner.RightTable + "`.`" + joiner.RightColumn + "` AND " } // Remove the trailing AND - querystr = querystr[0:len(querystr) - 4] - + querystr = querystr[0 : len(querystr)-4] + // Add support for BETWEEN x.x if len(where) != 0 { querystr += " WHERE" - for _, loc := range _process_where(where) { + for _, loc := range _processWhere(where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - halves := strings.Split(token.Contents,".") - if len(halves) == 2 { - querystr += " `" + halves[0] + "`.`" + halves[1] + "`" - } else { - querystr += " `" + token.Contents + "`" - } - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + halves := strings.Split(token.Contents, ".") + if len(halves) == 2 { + querystr += " `" + halves[0] + "`.`" + halves[1] + "`" + } else { + querystr += " `" + token.Contents + "`" + } + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - + if len(orderby) != 0 { querystr += " ORDER BY " for _, column := range _process_orderby(orderby) { querystr += column.Column + " " + strings.ToUpper(column.Order) + "," } - querystr = querystr[0:len(querystr) - 1] + querystr = querystr[0 : len(querystr)-1] } - + if limit != "" { querystr += " LIMIT " + limit } - + querystr = strings.TrimSpace(querystr) - adapter.push_statement(name,"select",querystr) + adapter.pushStatement(name, "select", querystr) return querystr, nil } func (adapter *Mysql_Adapter) SimpleInsertSelect(name string, ins DB_Insert, sel DB_Select) (string, error) { /* Insert Portion */ - - var querystr string = "INSERT INTO `" + ins.Table + "`(" - + + var querystr = "INSERT INTO `" + ins.Table + "`(" + // Escape the column names, just in case we've used a reserved keyword for _, column := range _process_columns(ins.Columns) { if column.Type == "function" { @@ -537,72 +536,72 @@ func (adapter *Mysql_Adapter) SimpleInsertSelect(name string, ins DB_Insert, sel querystr += "`" + column.Left + "`," } } - querystr = querystr[0:len(querystr) - 1] + ") SELECT" - + querystr = querystr[0:len(querystr)-1] + ") SELECT" + /* Select Portion */ - + for _, column := range _process_columns(sel.Columns) { var source, alias string - + // Escape the column names, just in case we've used a reserved keyword if column.Type == "function" || column.Type == "substitute" { source = column.Left } else { source = "`" + column.Left + "`" } - + if column.Alias != "" { alias = " AS `" + column.Alias + "`" } querystr += " " + source + alias + "," } - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + querystr += " FROM `" + sel.Table + "`" - + // Add support for BETWEEN x.x if len(sel.Where) != 0 { querystr += " WHERE" - for _, loc := range _process_where(sel.Where) { + for _, loc := range _processWhere(sel.Where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - querystr += " `" + token.Contents + "`" - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - + if len(sel.Orderby) != 0 { querystr += " ORDER BY " for _, column := range _process_orderby(sel.Orderby) { querystr += column.Column + " " + strings.ToUpper(column.Order) + "," } - querystr = querystr[0:len(querystr) - 1] + querystr = querystr[0 : len(querystr)-1] } - + if sel.Limit != "" { querystr += " LIMIT " + sel.Limit } - + querystr = strings.TrimSpace(querystr) - adapter.push_statement(name,"insert",querystr) + adapter.pushStatement(name, "insert", querystr) return querystr, nil } func (adapter *Mysql_Adapter) SimpleInsertLeftJoin(name string, ins DB_Insert, sel DB_Join) (string, error) { /* Insert Portion */ - - var querystr string = "INSERT INTO `" + ins.Table + "`(" - + + var querystr = "INSERT INTO `" + ins.Table + "`(" + // Escape the column names, just in case we've used a reserved keyword for _, column := range _process_columns(ins.Columns) { if column.Type == "function" { @@ -611,13 +610,13 @@ func (adapter *Mysql_Adapter) SimpleInsertLeftJoin(name string, ins DB_Insert, s querystr += "`" + column.Left + "`," } } - querystr = querystr[0:len(querystr) - 1] + ") SELECT" - + querystr = querystr[0:len(querystr)-1] + ") SELECT" + /* Select Portion */ - + for _, column := range _process_columns(sel.Columns) { var source, alias string - + // Escape the column names, just in case we've used a reserved keyword if column.Table != "" { source = "`" + column.Table + "`.`" + column.Left + "`" @@ -626,68 +625,68 @@ func (adapter *Mysql_Adapter) SimpleInsertLeftJoin(name string, ins DB_Insert, s } else { source = "`" + column.Left + "`" } - + if column.Alias != "" { alias = " AS `" + column.Alias + "`" } querystr += " " + source + alias + "," } - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + querystr += " FROM `" + sel.Table1 + "` LEFT JOIN `" + sel.Table2 + "` ON " - for _, joiner := range _process_joiner(sel.Joiners) { + for _, joiner := range _processJoiner(sel.Joiners) { querystr += "`" + joiner.LeftTable + "`.`" + joiner.LeftColumn + "` " + joiner.Operator + " `" + joiner.RightTable + "`.`" + joiner.RightColumn + "` AND " } - querystr = querystr[0:len(querystr) - 4] - + querystr = querystr[0 : len(querystr)-4] + // Add support for BETWEEN x.x if len(sel.Where) != 0 { querystr += " WHERE" - for _, loc := range _process_where(sel.Where) { + for _, loc := range _processWhere(sel.Where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - halves := strings.Split(token.Contents,".") - if len(halves) == 2 { - querystr += " `" + halves[0] + "`.`" + halves[1] + "`" - } else { - querystr += " `" + token.Contents + "`" - } - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + halves := strings.Split(token.Contents, ".") + if len(halves) == 2 { + querystr += " `" + halves[0] + "`.`" + halves[1] + "`" + } else { + querystr += " `" + token.Contents + "`" + } + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - + if len(sel.Orderby) != 0 { querystr += " ORDER BY " for _, column := range _process_orderby(sel.Orderby) { querystr += column.Column + " " + strings.ToUpper(column.Order) + "," } - querystr = querystr[0:len(querystr) - 1] + querystr = querystr[0 : len(querystr)-1] } - + if sel.Limit != "" { querystr += " LIMIT " + sel.Limit } - + querystr = strings.TrimSpace(querystr) - adapter.push_statement(name,"insert",querystr) + adapter.pushStatement(name, "insert", querystr) return querystr, nil } func (adapter *Mysql_Adapter) SimpleInsertInnerJoin(name string, ins DB_Insert, sel DB_Join) (string, error) { /* Insert Portion */ - - var querystr string = "INSERT INTO `" + ins.Table + "`(" - + + var querystr = "INSERT INTO `" + ins.Table + "`(" + // Escape the column names, just in case we've used a reserved keyword for _, column := range _process_columns(ins.Columns) { if column.Type == "function" { @@ -696,13 +695,13 @@ func (adapter *Mysql_Adapter) SimpleInsertInnerJoin(name string, ins DB_Insert, querystr += "`" + column.Left + "`," } } - querystr = querystr[0:len(querystr) - 1] + ") SELECT" - + querystr = querystr[0:len(querystr)-1] + ") SELECT" + /* Select Portion */ - + for _, column := range _process_columns(sel.Columns) { var source, alias string - + // Escape the column names, just in case we've used a reserved keyword if column.Table != "" { source = "`" + column.Table + "`.`" + column.Left + "`" @@ -711,60 +710,60 @@ func (adapter *Mysql_Adapter) SimpleInsertInnerJoin(name string, ins DB_Insert, } else { source = "`" + column.Left + "`" } - + if column.Alias != "" { alias = " AS `" + column.Alias + "`" } querystr += " " + source + alias + "," } - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + querystr += " FROM `" + sel.Table1 + "` INNER JOIN `" + sel.Table2 + "` ON " - for _, joiner := range _process_joiner(sel.Joiners) { + for _, joiner := range _processJoiner(sel.Joiners) { querystr += "`" + joiner.LeftTable + "`.`" + joiner.LeftColumn + "` " + joiner.Operator + " `" + joiner.RightTable + "`.`" + joiner.RightColumn + "` AND " } - querystr = querystr[0:len(querystr) - 4] - + querystr = querystr[0 : len(querystr)-4] + // Add support for BETWEEN x.x if len(sel.Where) != 0 { querystr += " WHERE" - for _, loc := range _process_where(sel.Where) { + for _, loc := range _processWhere(sel.Where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - halves := strings.Split(token.Contents,".") - if len(halves) == 2 { - querystr += " `" + halves[0] + "`.`" + halves[1] + "`" - } else { - querystr += " `" + token.Contents + "`" - } - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + halves := strings.Split(token.Contents, ".") + if len(halves) == 2 { + querystr += " `" + halves[0] + "`.`" + halves[1] + "`" + } else { + querystr += " `" + token.Contents + "`" + } + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - + if len(sel.Orderby) != 0 { querystr += " ORDER BY " for _, column := range _process_orderby(sel.Orderby) { querystr += column.Column + " " + strings.ToUpper(column.Order) + "," } - querystr = querystr[0:len(querystr) - 1] + querystr = querystr[0 : len(querystr)-1] } - + if sel.Limit != "" { querystr += " LIMIT " + sel.Limit } - + querystr = strings.TrimSpace(querystr) - adapter.push_statement(name,"insert",querystr) + adapter.pushStatement(name, "insert", querystr) return querystr, nil } @@ -775,39 +774,39 @@ func (adapter *Mysql_Adapter) SimpleCount(name string, table string, where strin if table == "" { return "", errors.New("You need a name for this table") } - - var querystr string = "SELECT COUNT(*) AS `count` FROM `" + table + "`" - + + var querystr = "SELECT COUNT(*) AS `count` FROM `" + table + "`" + // Add support for BETWEEN x.x if len(where) != 0 { querystr += " WHERE" //fmt.Println("SimpleCount:",name) //fmt.Println("where:",where) //fmt.Println("_process_where:",_process_where(where)) - for _, loc := range _process_where(where) { + for _, loc := range _processWhere(where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function","operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - querystr += " `" + token.Contents + "`" - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function", "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - + if limit != "" { querystr += " LIMIT " + limit } - + querystr = strings.TrimSpace(querystr) - adapter.push_statement(name,"select",querystr) + adapter.pushStatement(name, "select", querystr) return querystr, nil } @@ -827,7 +826,7 @@ func (adapter *Mysql_Adapter) Write() error { ` } } - + out := `// +build !pgsql !sqlite !mssql /* This file was generated by Gosora's Query Generator. Please try to avoid modifying this file, as it might change at any time. */ @@ -837,7 +836,9 @@ package main import "log" import "database/sql" +// nolint ` + stmts + ` +// nolint func _gen_mysql() (err error) { if dev.DebugMode { log.Print("Building the generated statements") @@ -846,16 +847,16 @@ func _gen_mysql() (err error) { return nil } ` - return write_file("./gen_mysql.go", out) + return writeFile("./gen_mysql.go", out) } // Internal methods, not exposed in the interface -func (adapter *Mysql_Adapter) push_statement(name string, stype string, querystr string) { - adapter.Buffer[name] = DB_Stmt{querystr,stype} - adapter.BufferOrder = append(adapter.BufferOrder,name) +func (adapter *Mysql_Adapter) pushStatement(name string, stype string, querystr string) { + adapter.Buffer[name] = DB_Stmt{querystr, stype} + adapter.BufferOrder = append(adapter.BufferOrder, name) } -func (adapter *Mysql_Adapter) stringy_type(ctype string) bool { +func (adapter *Mysql_Adapter) stringyType(ctype string) bool { ctype = strings.ToLower(ctype) return ctype == "varchar" || ctype == "tinytext" || ctype == "text" || ctype == "mediumtext" || ctype == "longtext" || ctype == "char" || ctype == "datetime" || ctype == "timestamp" || ctype == "time" || ctype == "date" } diff --git a/query_gen/lib/pgsql.go b/query_gen/lib/pgsql.go index aa7ab457..b86de6ea 100644 --- a/query_gen/lib/pgsql.go +++ b/query_gen/lib/pgsql.go @@ -7,14 +7,13 @@ import "errors" func init() { DB_Registry = append(DB_Registry, - &Pgsql_Adapter{Name:"pgsql",Buffer:make(map[string]DB_Stmt)}, + &Pgsql_Adapter{Name: "pgsql", Buffer: make(map[string]DB_Stmt)}, ) } -type Pgsql_Adapter struct -{ - Name string - Buffer map[string]DB_Stmt +type Pgsql_Adapter struct { + Name string + Buffer map[string]DB_Stmt BufferOrder []string // Map iteration order is random, so we need this to track the order, so we don't get huge diffs every commit } @@ -42,8 +41,8 @@ func (adapter *Pgsql_Adapter) CreateTable(name string, table string, charset str if len(columns) == 0 { return "", errors.New("You can't have a table with no columns") } - - var querystr string = "CREATE TABLE `" + table + "` (" + + var querystr = "CREATE TABLE `" + table + "` (" for _, column := range columns { if column.Auto_Increment { column.Type = "serial" @@ -52,29 +51,29 @@ func (adapter *Pgsql_Adapter) CreateTable(name string, table string, charset str } else if column.Type == "datetime" { column.Type = "timestamp" } - + var size string if column.Size > 0 { size = " (" + strconv.Itoa(column.Size) + ")" } - + var end string if column.Default != "" { end = " DEFAULT " - if adapter.stringy_type(column.Type) && column.Default != "''" { + if adapter.stringyType(column.Type) && column.Default != "''" { end += "'" + column.Default + "'" } else { end += column.Default } } - + if !column.Null { end += " not null" } - - querystr += "\n\t`"+column.Name+"` " + column.Type + size + end + "," + + querystr += "\n\t`" + column.Name + "` " + column.Type + size + end + "," } - + if len(keys) > 0 { for _, key := range keys { querystr += "\n\t" + key.Type @@ -82,15 +81,15 @@ func (adapter *Pgsql_Adapter) CreateTable(name string, table string, charset str querystr += " key" } querystr += "(" - for _, column := range strings.Split(key.Columns,",") { + for _, column := range strings.Split(key.Columns, ",") { querystr += "`" + column + "`," } - querystr = querystr[0:len(querystr) - 1] + ")," + querystr = querystr[0:len(querystr)-1] + ")," } } - - querystr = querystr[0:len(querystr) - 1] + "\n);" - adapter.push_statement(name,"create-table",querystr) + + querystr = querystr[0:len(querystr)-1] + "\n);" + adapter.pushStatement(name, "create-table", querystr) return querystr, nil } @@ -139,59 +138,59 @@ func (adapter *Pgsql_Adapter) SimpleUpdate(name string, table string, set string if set == "" { return "", errors.New("You need to set data in this update statement") } - var querystr string = "UPDATE `" + table + "` SET " + var querystr = "UPDATE `" + table + "` SET " for _, item := range _process_set(set) { querystr += "`" + item.Column + "` =" for _, token := range item.Expr { - switch(token.Type) { - case "function": - // TO-DO: Write a more sophisticated function parser on the utils side. - if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" { - token.Contents = "LOCALTIMESTAMP()" - } - querystr += " " + token.Contents + "" - case "operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - querystr += " `" + token.Contents + "`" - case "string": - querystr += " '" + token.Contents + "'" + switch token.Type { + case "function": + // TO-DO: Write a more sophisticated function parser on the utils side. + if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" { + token.Contents = "LOCALTIMESTAMP()" + } + querystr += " " + token.Contents + case "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" } } querystr += "," } - + // Remove the trailing comma - querystr = querystr[0:len(querystr) - 1] - + querystr = querystr[0 : len(querystr)-1] + // Add support for BETWEEN x.x if len(where) != 0 { querystr += " WHERE" - for _, loc := range _process_where(where) { + for _, loc := range _processWhere(where) { for _, token := range loc.Expr { - switch(token.Type) { - case "function": - // TO-DO: Write a more sophisticated function parser on the utils side. What's the situation in regards to case sensitivity? - if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" { - token.Contents = "LOCALTIMESTAMP()" - } - querystr += " " + token.Contents + "" - case "operator","number","substitute": - querystr += " " + token.Contents + "" - case "column": - querystr += " `" + token.Contents + "`" - case "string": - querystr += " '" + token.Contents + "'" - default: - panic("This token doesn't exist o_o") + switch token.Type { + case "function": + // TO-DO: Write a more sophisticated function parser on the utils side. What's the situation in regards to case sensitivity? + if strings.ToUpper(token.Contents) == "UTC_TIMESTAMP()" { + token.Contents = "LOCALTIMESTAMP()" + } + querystr += " " + token.Contents + case "operator", "number", "substitute": + querystr += " " + token.Contents + case "column": + querystr += " `" + token.Contents + "`" + case "string": + querystr += " '" + token.Contents + "'" + default: + panic("This token doesn't exist o_o") } } querystr += " AND" } - querystr = querystr[0:len(querystr) - 4] + querystr = querystr[0 : len(querystr)-4] } - - adapter.push_statement(name,"update",querystr) + + adapter.pushStatement(name, "update", querystr) return querystr, nil } @@ -317,7 +316,7 @@ func (adapter *Pgsql_Adapter) Write() error { ` } } - + out := `// +build pgsql // This file was generated by Gosora's Query Generator. Please try to avoid modifying this file, as it might change at any time. @@ -326,7 +325,9 @@ package main import "log" import "database/sql" +// nolint ` + stmts + ` +// nolint func _gen_pgsql() (err error) { if dev.DebugMode { log.Print("Building the generated statements") @@ -335,16 +336,16 @@ func _gen_pgsql() (err error) { return nil } ` - return write_file("./gen_pgsql.go", out) + return writeFile("./gen_pgsql.go", out) } // Internal methods, not exposed in the interface -func (adapter *Pgsql_Adapter) push_statement(name string, stype string, querystr string) { - adapter.Buffer[name] = DB_Stmt{querystr,stype} - adapter.BufferOrder = append(adapter.BufferOrder,name) +func (adapter *Pgsql_Adapter) pushStatement(name string, stype string, querystr string) { + adapter.Buffer[name] = DB_Stmt{querystr, stype} + adapter.BufferOrder = append(adapter.BufferOrder, name) } -func (adapter *Pgsql_Adapter) stringy_type(ctype string) bool { +func (adapter *Pgsql_Adapter) stringyType(ctype string) bool { ctype = strings.ToLower(ctype) return ctype == "char" || ctype == "varchar" || ctype == "timestamp" || ctype == "text" } diff --git a/query_gen/lib/utils.go b/query_gen/lib/utils.go index 9d69cd2a..a2de942d 100644 --- a/query_gen/lib/utils.go +++ b/query_gen/lib/utils.go @@ -9,33 +9,33 @@ func _process_columns(colstr string) (columns []DB_Column) { if colstr == "" { return columns } - colstr = strings.Replace(colstr," as "," AS ",-1) - for _, segment := range strings.Split(colstr,",") { + colstr = strings.Replace(colstr, " as ", " AS ", -1) + for _, segment := range strings.Split(colstr, ",") { var outcol DB_Column - dothalves := strings.Split(strings.TrimSpace(segment),".") - + dothalves := strings.Split(strings.TrimSpace(segment), ".") + var halves []string if len(dothalves) == 2 { outcol.Table = dothalves[0] - halves = strings.Split(dothalves[1]," AS ") + halves = strings.Split(dothalves[1], " AS ") } else { - halves = strings.Split(dothalves[0]," AS ") + halves = strings.Split(dothalves[0], " AS ") } - + halves[0] = strings.TrimSpace(halves[0]) if len(halves) == 2 { outcol.Alias = strings.TrimSpace(halves[1]) } - if halves[0][len(halves[0]) - 1] == ')' { + if halves[0][len(halves[0])-1] == ')' { outcol.Type = "function" } else if halves[0] == "?" { outcol.Type = "substitute" } else { outcol.Type = "column" } - + outcol.Left = halves[0] - columns = append(columns,outcol) + columns = append(columns, outcol) } return columns } @@ -44,65 +44,64 @@ func _process_orderby(orderstr string) (order []DB_Order) { if orderstr == "" { return order } - for _, segment := range strings.Split(orderstr,",") { + for _, segment := range strings.Split(orderstr, ",") { var outorder DB_Order - halves := strings.Split(strings.TrimSpace(segment)," ") + halves := strings.Split(strings.TrimSpace(segment), " ") if len(halves) != 2 { continue } outorder.Column = halves[0] outorder.Order = strings.ToLower(halves[1]) - order = append(order,outorder) + order = append(order, outorder) } return order } -func _process_joiner(joinstr string) (joiner []DB_Joiner) { +func _processJoiner(joinstr string) (joiner []DB_Joiner) { if joinstr == "" { return joiner } - joinstr = strings.Replace(joinstr," on "," ON ",-1) - joinstr = strings.Replace(joinstr," and "," AND ",-1) - for _, segment := range strings.Split(joinstr," AND ") { + joinstr = strings.Replace(joinstr, " on ", " ON ", -1) + joinstr = strings.Replace(joinstr, " and ", " AND ", -1) + for _, segment := range strings.Split(joinstr, " AND ") { var outjoin DB_Joiner var parseOffset int var left, right string - - left, parseOffset = _get_identifier(segment, parseOffset) - outjoin.Operator, parseOffset = _get_operator(segment, parseOffset + 1) - right, parseOffset = _get_identifier(segment, parseOffset + 1) - - - left_column := strings.Split(left,".") - right_column := strings.Split(right,".") + + left, parseOffset = _getIdentifier(segment, parseOffset) + outjoin.Operator, parseOffset = _getOperator(segment, parseOffset+1) + right, parseOffset = _getIdentifier(segment, parseOffset+1) + + left_column := strings.Split(left, ".") + right_column := strings.Split(right, ".") outjoin.LeftTable = strings.TrimSpace(left_column[0]) outjoin.RightTable = strings.TrimSpace(right_column[0]) outjoin.LeftColumn = strings.TrimSpace(left_column[1]) outjoin.RightColumn = strings.TrimSpace(right_column[1]) - - joiner = append(joiner,outjoin) + + joiner = append(joiner, outjoin) } return joiner } -func _process_where(wherestr string) (where []DB_Where) { +func _processWhere(wherestr string) (where []DB_Where) { if wherestr == "" { return where } - wherestr = strings.Replace(wherestr," and "," AND ",-1) - + wherestr = strings.Replace(wherestr, " and ", " AND ", -1) + var buffer string var optype int // 0: None, 1: Number, 2: Column, 3: Function, 4: String, 5: Operator - for _, segment := range strings.Split(wherestr," AND ") { + for _, segment := range strings.Split(wherestr, " AND ") { var tmp_where DB_Where segment += ")" for i := 0; i < len(segment); i++ { char := segment[i] //fmt.Println("optype",optype) - switch(optype) { + switch optype { case 0: // unknown //fmt.Println("case 0:",char,string(char)) - if ('0' <= char && char <= '9') { + if '0' <= char && char <= '9' { optype = 1 buffer = string(char) } else if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' { @@ -116,16 +115,16 @@ func _process_where(wherestr string) (where []DB_Where) { buffer = string(char) } else if char == '?' { //fmt.Println("Expr:","?") - tmp_where.Expr = append(tmp_where.Expr,DB_Token{"?","substitute"}) + tmp_where.Expr = append(tmp_where.Expr, DB_Token{"?", "substitute"}) } case 1: // number - if ('0' <= char && char <= '9') { + if '0' <= char && char <= '9' { buffer += string(char) } else { optype = 0 i-- //fmt.Println("Expr:",buffer) - tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"number"}) + tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "number"}) } case 2: // column if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '.' || char == '_' { @@ -137,22 +136,22 @@ func _process_where(wherestr string) (where []DB_Where) { optype = 0 i-- //fmt.Println("Expr:",buffer) - tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"column"}) + tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "column"}) } case 3: // function - var pre_i int = i + var preI = i //fmt.Println("buffer",buffer) //fmt.Println("len(halves)",len(halves[1])) - //fmt.Println("pre_i",string(halves[1][pre_i])) - //fmt.Println("msg prior to pre_i",halves[1][0:pre_i]) - i = _skip_function_call(segment,i-1) + //fmt.Println("preI",string(halves[1][preI])) + //fmt.Println("msg prior to preI",halves[1][0:preI]) + i = _skipFunctionCall(segment, i-1) //fmt.Println("i",i) //fmt.Println("msg prior to i-1",halves[1][0:i-1]) //fmt.Println("string(i-1)",string(halves[1][i-1])) //fmt.Println("string(i)",string(halves[1][i])) - buffer += segment[pre_i:i] + string(segment[i]) + buffer += segment[preI:i] + string(segment[i]) //fmt.Println("Expr:",buffer) - tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"function"}) + tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "function"}) optype = 0 case 4: // string if char != '\'' { @@ -160,7 +159,7 @@ func _process_where(wherestr string) (where []DB_Where) { } else { optype = 0 //fmt.Println("Expr:",buffer) - tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"string"}) + tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "string"}) } case 5: // operator if _is_op_byte(char) { @@ -169,13 +168,13 @@ func _process_where(wherestr string) (where []DB_Where) { optype = 0 i-- //fmt.Println("Expr:",buffer) - tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"operator"}) + tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "operator"}) } default: panic("Bad optype in _process_where") } } - where = append(where,tmp_where) + where = append(where, tmp_where) } return where } @@ -185,46 +184,46 @@ func _process_set(setstr string) (setter []DB_Setter) { return setter } //fmt.Println("setstr",setstr) - + // First pass, splitting the string by commas while ignoring the innards of functions var setset []string var buffer string - var last_item int + var lastItem int setstr += "," - for i := 0; i < len(setstr); i++ { + for i := 0; i < len(setstr); i++ { if setstr[i] == '(' { - i = _skip_function_call(setstr,i-1) - setset = append(setset,setstr[last_item:i+1]) + i = _skipFunctionCall(setstr, i-1) + setset = append(setset, setstr[lastItem:i+1]) buffer = "" - last_item = i + 2 + lastItem = i + 2 } else if setstr[i] == ',' && buffer != "" { - setset = append(setset,buffer) + setset = append(setset, buffer) buffer = "" - last_item = i + 1 + lastItem = i + 1 } else if (setstr[i] > 32) && setstr[i] != ',' && setstr[i] != ')' { buffer += string(setstr[i]) } } - + // Second pass. Break this setitem into manageable chunks buffer = "" for _, setitem := range setset { var tmp_setter DB_Setter - halves := strings.Split(setitem,"=") + halves := strings.Split(setitem, "=") if len(halves) != 2 { continue } tmp_setter.Column = strings.TrimSpace(halves[0]) - + halves[1] += ")" var optype int // 0: None, 1: Number, 2: Column, 3: Function, 4: String, 5: Operator //fmt.Println("halves[1]",halves[1]) for i := 0; i < len(halves[1]); i++ { char := halves[1][i] //fmt.Println("optype",optype) - switch(optype) { + switch optype { case 0: // unknown - if ('0' <= char && char <= '9') { + if '0' <= char && char <= '9' { optype = 1 buffer = string(char) } else if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' { @@ -238,16 +237,16 @@ func _process_set(setstr string) (setter []DB_Setter) { buffer = string(char) } else if char == '?' { //fmt.Println("Expr:","?") - tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{"?","substitute"}) + tmp_setter.Expr = append(tmp_setter.Expr, DB_Token{"?", "substitute"}) } case 1: // number - if ('0' <= char && char <= '9') { + if '0' <= char && char <= '9' { buffer += string(char) } else { optype = 0 i-- //fmt.Println("Expr:",buffer) - tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"number"}) + tmp_setter.Expr = append(tmp_setter.Expr, DB_Token{buffer, "number"}) } case 2: // column if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' { @@ -259,22 +258,22 @@ func _process_set(setstr string) (setter []DB_Setter) { optype = 0 i-- //fmt.Println("Expr:",buffer) - tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"column"}) + tmp_setter.Expr = append(tmp_setter.Expr, DB_Token{buffer, "column"}) } case 3: // function - var pre_i int = i + var preI = i //fmt.Println("buffer",buffer) //fmt.Println("len(halves)",len(halves[1])) - //fmt.Println("pre_i",string(halves[1][pre_i])) - //fmt.Println("msg prior to pre_i",halves[1][0:pre_i]) - i = _skip_function_call(halves[1],i-1) + //fmt.Println("preI",string(halves[1][preI])) + //fmt.Println("msg prior to preI",halves[1][0:preI]) + i = _skipFunctionCall(halves[1], i-1) //fmt.Println("i",i) //fmt.Println("msg prior to i-1",halves[1][0:i-1]) //fmt.Println("string(i-1)",string(halves[1][i-1])) //fmt.Println("string(i)",string(halves[1][i])) - buffer += halves[1][pre_i:i] + string(halves[1][i]) + buffer += halves[1][preI:i] + string(halves[1][i]) //fmt.Println("Expr:",buffer) - tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"function"}) + tmp_setter.Expr = append(tmp_setter.Expr, DB_Token{buffer, "function"}) optype = 0 case 4: // string if char != '\'' { @@ -282,7 +281,7 @@ func _process_set(setstr string) (setter []DB_Setter) { } else { optype = 0 //fmt.Println("Expr:",buffer) - tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"string"}) + tmp_setter.Expr = append(tmp_setter.Expr, DB_Token{buffer, "string"}) } case 5: // operator if _is_op_byte(char) { @@ -291,20 +290,20 @@ func _process_set(setstr string) (setter []DB_Setter) { optype = 0 i-- //fmt.Println("Expr:",buffer) - tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"operator"}) + tmp_setter.Expr = append(tmp_setter.Expr, DB_Token{buffer, "operator"}) } default: panic("Bad optype in _process_set") } } - setter = append(setter,tmp_setter) + setter = append(setter, tmp_setter) } //fmt.Println("setter",setter) return setter } -func _process_limit(limitstr string) (limiter DB_Limit) { - halves := strings.Split(limitstr,",") +func _processLimit(limitstr string) (limiter DB_Limit) { + halves := strings.Split(limitstr, ",") if len(halves) == 2 { limiter.Offset = halves[0] limiter.MaxCount = halves[1] @@ -322,23 +321,23 @@ func _is_op_rune(char rune) bool { return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/' } -func _process_fields(fieldstr string) (fields []DB_Field) { +func _processFields(fieldstr string) (fields []DB_Field) { if fieldstr == "" { return fields } var buffer string - var last_item int + var lastItem int fieldstr += "," - for i := 0; i < len(fieldstr); i++ { + for i := 0; i < len(fieldstr); i++ { if fieldstr[i] == '(' { - i = _skip_function_call(fieldstr,i-1) - fields = append(fields,DB_Field{Name:fieldstr[last_item:i+1],Type:_get_identifier_type(fieldstr[last_item:i+1])}) + i = _skipFunctionCall(fieldstr, i-1) + fields = append(fields, DB_Field{Name: fieldstr[lastItem : i+1], Type: _getIdentifierType(fieldstr[lastItem : i+1])}) buffer = "" - last_item = i + 2 + lastItem = i + 2 } else if fieldstr[i] == ',' && buffer != "" { - fields = append(fields,DB_Field{Name:buffer,Type:_get_identifier_type(buffer)}) + fields = append(fields, DB_Field{Name: buffer, Type: _getIdentifierType(buffer)}) buffer = "" - last_item = i + 1 + lastItem = i + 1 } else if (fieldstr[i] > 32) && fieldstr[i] != ',' && fieldstr[i] != ')' { buffer += string(fieldstr[i]) } @@ -346,9 +345,9 @@ func _process_fields(fieldstr string) (fields []DB_Field) { return fields } -func _get_identifier_type(identifier string) string { +func _getIdentifierType(identifier string) string { if ('a' <= identifier[0] && identifier[0] <= 'z') || ('A' <= identifier[0] && identifier[0] <= 'Z') { - if identifier[len(identifier) - 1] == ')' { + if identifier[len(identifier)-1] == ')' { return "function" } return "column" @@ -359,12 +358,12 @@ func _get_identifier_type(identifier string) string { return "literal" } -func _get_identifier(segment string, startOffset int) (out string, i int) { +func _getIdentifier(segment string, startOffset int) (out string, i int) { segment = strings.TrimSpace(segment) segment += " " // Avoid overflow bugs with slicing for i = startOffset; i < len(segment); i++ { if segment[i] == '(' { - i = _skip_function_call(segment,i) + i = _skipFunctionCall(segment, i) return strings.TrimSpace(segment[startOffset:i]), (i - 1) } if (segment[i] == ' ' || _is_op_byte(segment[i])) && i != startOffset { @@ -374,7 +373,7 @@ func _get_identifier(segment string, startOffset int) (out string, i int) { return strings.TrimSpace(segment[startOffset:]), (i - 1) } -func _get_operator(segment string, startOffset int) (out string, i int) { +func _getOperator(segment string, startOffset int) (out string, i int) { segment = strings.TrimSpace(segment) segment += " " // Avoid overflow bugs with slicing for i = startOffset; i < len(segment); i++ { @@ -385,15 +384,15 @@ func _get_operator(segment string, startOffset int) (out string, i int) { return strings.TrimSpace(segment[startOffset:]), (i - 1) } -func _skip_function_call(data string, index int) int { - var brace_count int - for ;index < len(data); index++{ +func _skipFunctionCall(data string, index int) int { + var braceCount int + for ; index < len(data); index++ { char := data[index] if char == '(' { - brace_count++ + braceCount++ } else if char == ')' { - brace_count-- - if brace_count == 0 { + braceCount-- + if braceCount == 0 { return index } } @@ -401,7 +400,7 @@ func _skip_function_call(data string, index int) int { return index } -func write_file(name string, content string) (err error) { +func writeFile(name string, content string) (err error) { f, err := os.Create(name) if err != nil { return err @@ -410,7 +409,9 @@ func write_file(name string, content string) (err error) { if err != nil { return err } - f.Sync() - f.Close() - return + err = f.Sync() + if err != nil { + return err + } + return f.Close() } diff --git a/reply.go b/reply.go index 37edf916..201d13a2 100644 --- a/reply.go +++ b/reply.go @@ -1,60 +1,64 @@ -/* Copyright Azareal 2016 - 2017 */ +/* +* +* Reply Resources File +* Copyright Azareal 2016 - 2018 +* + */ package main // Should we add a reply store to centralise all the reply logic? Would this cover profile replies too or would that be seperate? type Reply struct /* Should probably rename this to ReplyUser and rename ReplyShort to Reply */ { - ID int - ParentID int - Content string - ContentHtml string - CreatedBy int - UserLink string + ID int + ParentID int + Content string + ContentHtml string + CreatedBy int + UserLink string CreatedByName string - Group int - CreatedAt string - LastEdit int - LastEditBy int - Avatar string - ClassName string - ContentLines int - Tag string - URL string - URLPrefix string - URLName string - Level int - IpAddress string - Liked bool - LikeCount int - ActionType string - ActionIcon string + Group int + CreatedAt string + LastEdit int + LastEditBy int + Avatar string + ClassName string + ContentLines int + Tag string + URL string + URLPrefix string + URLName string + Level int + IPAddress string + Liked bool + LikeCount int + ActionType string + ActionIcon string } -type ReplyShort struct -{ - ID int - ParentID int - Content string - CreatedBy int - Group int - CreatedAt string - LastEdit int - LastEditBy int +type ReplyShort struct { + ID int + ParentID int + Content string + CreatedBy int + Group int + CreatedAt string + LastEdit int + LastEditBy int ContentLines int - IpAddress string - Liked bool - LikeCount int + IPAddress string + Liked bool + LikeCount int } -func get_reply(id int) (*ReplyShort, error) { - reply := ReplyShort{ID:id} - err := get_reply_stmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IpAddress, &reply.LikeCount) +func getReply(id int) (*ReplyShort, error) { + reply := ReplyShort{ID: id} + err := get_reply_stmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress, &reply.LikeCount) return &reply, err } -func get_user_reply(id int) (*ReplyShort, error) { - reply := ReplyShort{ID:id} - err := get_user_reply_stmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IpAddress) +func getUserReply(id int) (*ReplyShort, error) { + reply := ReplyShort{ID: id} + err := get_user_reply_stmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress) return &reply, err } diff --git a/router_gen/routes.go b/router_gen/routes.go index 198ee08e..262b54f9 100644 --- a/router_gen/routes.go +++ b/router_gen/routes.go @@ -1,86 +1,86 @@ package main type Route struct { - Name string - Path string + Name string + Path string Before string - Vars []string + Vars []string } type RouteGroup struct { - Path string + Path string Routes []Route } func addRoute(fname string, path string, before string, vars ...string) { - route_list = append(route_list,Route{fname,path,before,vars}) + route_list = append(route_list, Route{fname, path, before, vars}) } func addRouteGroup(path string, routes ...Route) { - route_groups = append(route_groups,RouteGroup{path,routes}) + route_groups = append(route_groups, RouteGroup{path, routes}) } func routes() { //addRoute("default_route","","") - addRoute("route_api","/api/","") + addRoute("route_api", "/api/", "") ///addRoute("route_static","/static/","req.URL.Path += extra_data") - addRoute("route_overview","/overview/","") + addRoute("route_overview", "/overview/", "") //addRoute("route_custom_page","/pages/",""/*,"&extra_data"*/) - addRoute("route_forums","/forums/",""/*,"&forums"*/) - addRoute("route_forum","/forum/","","extra_data") + addRoute("route_forums", "/forums/", "" /*,"&forums"*/) + addRoute("route_forum", "/forum/", "", "extra_data") //addRoute("route_topic_create","/topics/create/","","extra_data") //addRoute("route_topics","/topics/",""/*,"&groups","&forums"*/) addRouteGroup("/report/", - Route{"route_report_submit","/report/submit/","",[]string{"extra_data"}}, + Route{"route_report_submit", "/report/submit/", "", []string{"extra_data"}}, ) addRouteGroup("/topics/", - Route{"route_topics","/topics/","",[]string{}}, - Route{"route_topic_create","/topics/create/","",[]string{"extra_data"}}, + Route{"route_topics", "/topics/", "", []string{}}, + Route{"route_topic_create", "/topics/create/", "", []string{"extra_data"}}, ) // The Control Panel addRouteGroup("/panel/", - Route{"route_panel","/panel/","",[]string{}}, - Route{"route_panel_forums","/panel/forums/","",[]string{}}, - Route{"route_panel_forums_create_submit","/panel/forums/create/","",[]string{}}, - Route{"route_panel_forums_delete","/panel/forums/delete/","",[]string{"extra_data"}}, - Route{"route_panel_forums_delete_submit","/panel/forums/delete/submit/","",[]string{"extra_data"}}, - Route{"route_panel_forums_edit","/panel/forums/edit/","",[]string{"extra_data"}}, - Route{"route_panel_forums_edit_submit","/panel/forums/edit/submit/","",[]string{"extra_data"}}, - Route{"route_panel_forums_edit_perms_submit","/panel/forums/edit/perms/submit/","",[]string{"extra_data"}}, + Route{"route_panel", "/panel/", "", []string{}}, + Route{"route_panel_forums", "/panel/forums/", "", []string{}}, + Route{"route_panel_forums_create_submit", "/panel/forums/create/", "", []string{}}, + Route{"route_panel_forums_delete", "/panel/forums/delete/", "", []string{"extra_data"}}, + Route{"route_panel_forums_delete_submit", "/panel/forums/delete/submit/", "", []string{"extra_data"}}, + Route{"route_panel_forums_edit", "/panel/forums/edit/", "", []string{"extra_data"}}, + Route{"route_panel_forums_edit_submit", "/panel/forums/edit/submit/", "", []string{"extra_data"}}, + Route{"route_panel_forums_edit_perms_submit", "/panel/forums/edit/perms/submit/", "", []string{"extra_data"}}, - Route{"route_panel_settings","/panel/settings/","",[]string{}}, - Route{"route_panel_setting","/panel/settings/edit/","",[]string{"extra_data"}}, - Route{"route_panel_setting_edit","/panel/settings/edit/submit/","",[]string{"extra_data"}}, - - Route{"route_panel_word_filters","/panel/settings/word-filters/","",[]string{}}, - Route{"route_panel_word_filters_create","/panel/settings/word-filters/create/","",[]string{}}, - Route{"route_panel_word_filters_edit","/panel/settings/word-filters/edit/","",[]string{"extra_data"}}, - Route{"route_panel_word_filters_edit_submit","/panel/settings/word-filters/edit/submit/","",[]string{"extra_data"}}, - Route{"route_panel_word_filters_delete_submit","/panel/settings/word-filters/delete/submit/","",[]string{"extra_data"}}, + Route{"route_panel_settings", "/panel/settings/", "", []string{}}, + Route{"route_panel_setting", "/panel/settings/edit/", "", []string{"extra_data"}}, + Route{"route_panel_setting_edit", "/panel/settings/edit/submit/", "", []string{"extra_data"}}, - Route{"route_panel_themes","/panel/themes/","",[]string{}}, - Route{"route_panel_themes_default","/panel/themes/default/","",[]string{"extra_data"}}, + Route{"route_panel_word_filters", "/panel/settings/word-filters/", "", []string{}}, + Route{"route_panel_word_filters_create", "/panel/settings/word-filters/create/", "", []string{}}, + Route{"route_panel_word_filters_edit", "/panel/settings/word-filters/edit/", "", []string{"extra_data"}}, + Route{"route_panel_word_filters_edit_submit", "/panel/settings/word-filters/edit/submit/", "", []string{"extra_data"}}, + Route{"route_panel_word_filters_delete_submit", "/panel/settings/word-filters/delete/submit/", "", []string{"extra_data"}}, - Route{"route_panel_plugins","/panel/plugins/","",[]string{}}, - Route{"route_panel_plugins_activate","/panel/plugins/activate/","",[]string{"extra_data"}}, - Route{"route_panel_plugins_deactivate","/panel/plugins/deactivate/","",[]string{"extra_data"}}, - Route{"route_panel_plugins_install","/panel/plugins/install/","",[]string{"extra_data"}}, + Route{"route_panel_themes", "/panel/themes/", "", []string{}}, + Route{"route_panel_themes_set_default", "/panel/themes/default/", "", []string{"extra_data"}}, - Route{"route_panel_users","/panel/users/","",[]string{}}, - Route{"route_panel_users_edit","/panel/users/edit/","",[]string{"extra_data"}}, - Route{"route_panel_users_edit_submit","/panel/users/edit/submit/","",[]string{"extra_data"}}, + Route{"route_panel_plugins", "/panel/plugins/", "", []string{}}, + Route{"route_panel_plugins_activate", "/panel/plugins/activate/", "", []string{"extra_data"}}, + Route{"route_panel_plugins_deactivate", "/panel/plugins/deactivate/", "", []string{"extra_data"}}, + Route{"route_panel_plugins_install", "/panel/plugins/install/", "", []string{"extra_data"}}, - Route{"route_panel_groups","/panel/groups/","",[]string{}}, - Route{"route_panel_groups_edit","/panel/groups/edit/","",[]string{"extra_data"}}, - Route{"route_panel_groups_edit_perms","/panel/groups/edit/perms/","",[]string{"extra_data"}}, - Route{"route_panel_groups_edit_submit","/panel/groups/edit/submit/","",[]string{"extra_data"}}, - Route{"route_panel_groups_edit_perms_submit","/panel/groups/edit/perms/submit/","",[]string{"extra_data"}}, - Route{"route_panel_groups_create_submit","/panel/groups/create/","",[]string{}}, + Route{"route_panel_users", "/panel/users/", "", []string{}}, + Route{"route_panel_users_edit", "/panel/users/edit/", "", []string{"extra_data"}}, + Route{"route_panel_users_edit_submit", "/panel/users/edit/submit/", "", []string{"extra_data"}}, - Route{"route_panel_logs_mod","/panel/logs/mod/","",[]string{}}, - Route{"route_panel_debug","/panel/debug/","",[]string{}}, + Route{"route_panel_groups", "/panel/groups/", "", []string{}}, + Route{"route_panel_groups_edit", "/panel/groups/edit/", "", []string{"extra_data"}}, + Route{"route_panel_groups_edit_perms", "/panel/groups/edit/perms/", "", []string{"extra_data"}}, + Route{"route_panel_groups_edit_submit", "/panel/groups/edit/submit/", "", []string{"extra_data"}}, + Route{"route_panel_groups_edit_perms_submit", "/panel/groups/edit/perms/submit/", "", []string{"extra_data"}}, + Route{"route_panel_groups_create_submit", "/panel/groups/create/", "", []string{}}, + + Route{"route_panel_logs_mod", "/panel/logs/mod/", "", []string{}}, + Route{"route_panel_debug", "/panel/debug/", "", []string{}}, ) } diff --git a/routes.go b/routes.go index 539c26d2..503f9281 100644 --- a/routes.go +++ b/routes.go @@ -1,33 +1,38 @@ -/* Copyright Azareal 2016 - 2017 */ +/* +* +* Gosora Route Handlers +* Copyright Azareal 2016 - 2018 +* + */ package main import ( "log" //"fmt" - "strconv" "bytes" - "regexp" - "strings" - "time" + "html" "io" - "os" "net" "net/http" - "html" + "os" + "regexp" + "strconv" + "strings" + "time" "./query_gen/lib" ) // A blank list to fill out that parameter in Page for routes which don't use it var tList []interface{} -var nList []string -var hvars HeaderVars -var extData ExtData -var success_json_bytes []byte = []byte(`{"success":"1"}`) -var cacheControlMaxAge string = "max-age=" + strconv.Itoa(day) + +//var nList []string +var hvars *HeaderVars // We might need to rethink this now that it's a pointer +var successJSONBytes = []byte(`{"success":"1"}`) +var cacheControlMaxAge = "max-age=" + strconv.Itoa(day) func init() { - hvars.Site = site + hvars = &HeaderVars{Site: site} } type HttpsRedirect struct { @@ -38,20 +43,20 @@ func (red *HttpsRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) { if len(req.URL.RawQuery) > 0 { dest += "?" + req.URL.RawQuery } - http.Redirect(w,req,dest,http.StatusTemporaryRedirect) + http.Redirect(w, req, dest, http.StatusTemporaryRedirect) } // GET functions -func route_static(w http.ResponseWriter, r *http.Request){ +func route_static(w http.ResponseWriter, r *http.Request) { //log.Print("Outputting static file '" + r.URL.Path + "'") - file, ok := static_files[r.URL.Path] + file, ok := staticFiles[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)) { + 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 } @@ -60,11 +65,11 @@ func route_static(w http.ResponseWriter, r *http.Request){ h.Set("Content-Type", file.Mimetype) //Cache-Control: max-age=31536000 h.Set("Cache-Control", cacheControlMaxAge) - h.Set("Vary","Accept-Encoding") + h.Set("Vary", "Accept-Encoding") //http.ServeContent(w,r,r.URL.Path,file.Info.ModTime(),file) //w.Write(file.Data) - if strings.Contains(r.Header.Get("Accept-Encoding"),"gzip") { - h.Set("Content-Encoding","gzip") + if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { + h.Set("Content-Encoding", "gzip") h.Set("Content-Length", strconv.FormatInt(file.GzipLength, 10)) io.Copy(w, bytes.NewReader(file.GzipData)) // Use w.Write instead? } else { @@ -89,7 +94,7 @@ func route_fstatic(w http.ResponseWriter, r *http.Request){ // TO-DO: Add a sitemap // TO-DO: Add an API so that plugins can register disallowed areas. E.g. /groups/join for plugin_socialgroups func route_robots_txt(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(`User-agent: * + _, _ = w.Write([]byte(`User-agent: * Disallow: /panel/ Disallow: /topics/create/ Disallow: /user/edit/ @@ -97,96 +102,96 @@ Disallow: /accounts/ `)) } -func route_overview(w http.ResponseWriter, r *http.Request, user User){ - headerVars, ok := SessionCheck(w,r,&user) +func route_overview(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } - BuildWidgets("overview",nil,&headerVars,r) + BuildWidgets("overview", nil, headerVars, r) - pi := Page{"Overview",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_overview"] != nil { - if run_pre_render_hook("pre_render_overview", w, r, &user, &pi) { + pi := Page{"Overview", user, headerVars, tList, nil} + if preRenderHooks["pre_render_overview"] != nil { + if runPreRenderHook("pre_render_overview", w, r, &user, &pi) { return } } - err := templates.ExecuteTemplate(w,"overview.html",pi) + err := templates.ExecuteTemplate(w, "overview.html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func route_custom_page(w http.ResponseWriter, r *http.Request, user User){ - headerVars, ok := SessionCheck(w,r,&user) +func route_custom_page(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } name := r.URL.Path[len("/pages/"):] - if templates.Lookup("page_" + name) == nil { - NotFound(w,r) + if templates.Lookup("page_"+name) == nil { + NotFound(w, r) return } - BuildWidgets("custom_page",name,&headerVars,r) + BuildWidgets("custom_page", name, headerVars, r) - pi := Page{"Page",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_custom_page"] != nil { - if run_pre_render_hook("pre_render_custom_page", w, r, &user, &pi) { + pi := Page{"Page", user, headerVars, tList, nil} + if preRenderHooks["pre_render_custom_page"] != nil { + if runPreRenderHook("pre_render_custom_page", w, r, &user, &pi) { return } } - err := templates.ExecuteTemplate(w,"page_" + name,pi) + err := templates.ExecuteTemplate(w, "page_"+name, pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } // TO-DO: Paginate this -func route_topics(w http.ResponseWriter, r *http.Request, user User){ - headerVars, ok := SessionCheck(w,r,&user) +func route_topics(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } - BuildWidgets("topics",nil,&headerVars,r) + BuildWidgets("topics", nil, headerVars, r) var qlist string var fidList []interface{} group := groups[user.Group] for _, fid := range group.CanSee { if fstore.DirtyGet(fid).Name != "" { - fidList = append(fidList,strconv.Itoa(fid)) + fidList = append(fidList, strconv.Itoa(fid)) qlist += "?," } } - qlist = qlist[0:len(qlist) - 1] + qlist = qlist[0 : len(qlist)-1] var topicList []*TopicsRow //stmt, err := qgen.Builder.SimpleLeftJoin("topics","users","topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, topics.postCount, topics.likeCount, users.name, users.avatar","topics.createdBy = users.uid","parentID IN("+qlist+")","topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC","") - stmt, err := qgen.Builder.SimpleSelect("topics","tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount","parentID IN("+qlist+")","sticky DESC, lastReplyAt DESC, createdBy DESC","") + stmt, err := qgen.Builder.SimpleSelect("topics", "tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount", "parentID IN("+qlist+")", "sticky DESC, lastReplyAt DESC, createdBy DESC", "") if err != nil { - InternalError(err,w) + InternalError(err, w) return } rows, err := stmt.Query(fidList...) if err != nil { - InternalError(err,w) + InternalError(err, w) return } defer rows.Close() - var reqUserList map[int]bool = make(map[int]bool) + var reqUserList = make(map[int]bool) for rows.Next() { topicItem := TopicsRow{ID: 0} - err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.Is_Closed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.LastReplyBy, &topicItem.ParentID, &topicItem.PostCount, &topicItem.LikeCount) + err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.IsClosed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.LastReplyBy, &topicItem.ParentID, &topicItem.PostCount, &topicItem.LikeCount) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - topicItem.Link = build_topic_url(name_to_slug(topicItem.Title),topicItem.ID) + topicItem.Link = buildTopicURL(nameToSlug(topicItem.Title), topicItem.ID) forum := fstore.DirtyGet(topicItem.ParentID) if topicItem.ParentID >= 0 { @@ -197,17 +202,17 @@ func route_topics(w http.ResponseWriter, r *http.Request, user User){ //topicItem.ForumLink = "" } - /*topicItem.CreatedAt, err = relative_time(topicItem.CreatedAt) + /*topicItem.CreatedAt, err = relativeTime(topicItem.CreatedAt) if err != nil { replyItem.CreatedAt = "" }*/ - topicItem.LastReplyAt, err = relative_time(topicItem.LastReplyAt) + topicItem.LastReplyAt, err = relativeTime(topicItem.LastReplyAt) if err != nil { - InternalError(err,w) + InternalError(err, w) } - if hooks["topics_topic_row_assign"] != nil { - run_vhook("topics_topic_row_assign", &topicItem, &forum) + if vhooks["topics_topic_row_assign"] != nil { + runVhook("topics_topic_row_assign", &topicItem, &forum) } topicList = append(topicList, &topicItem) reqUserList[topicItem.CreatedBy] = true @@ -215,14 +220,14 @@ func route_topics(w http.ResponseWriter, r *http.Request, user User){ } err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) return } // Convert the user ID map to a slice, then bulk load the users - var idSlice []int = make([]int,len(reqUserList)) + var idSlice = make([]int, len(reqUserList)) var i int - for userID, _ := range reqUserList { + for userID := range reqUserList { idSlice[i] = userID i++ } @@ -230,7 +235,7 @@ func route_topics(w http.ResponseWriter, r *http.Request, user User){ // TO-DO: What if a user is deleted via the Control Panel? userList, err := users.BulkCascadeGetMap(idSlice) if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -241,94 +246,88 @@ func route_topics(w http.ResponseWriter, r *http.Request, user User){ topicItem.LastUser = userList[topicItem.LastReplyBy] } - pi := TopicsPage{"Topic List",user,headerVars,topicList,extData} - if pre_render_hooks["pre_render_topic_list"] != nil { - if run_pre_render_hook("pre_render_topic_list", w, r, &user, &pi) { + pi := TopicsPage{"Topic List", user, headerVars, topicList} + if preRenderHooks["pre_render_topic_list"] != nil { + if runPreRenderHook("pre_render_topic_list", w, r, &user, &pi) { return } } - - // TO-DO: Is there a more type-safe way of doing this? - //RunThemeTemplate(defaultTheme,"topics",pi,w) - //RunTemplate(GetThemeTemplate(defaultTheme,"topics"),pi,w) - //GetThemeTemplate(defaultTheme,"topics").(func(TopicsPage,http.ResponseWriter))(pi,w) - //GetThemeTemplate(defaultTheme,"topics").Execute(pi,w) - template_topics_handle(pi,w) + RunThemeTemplate(headerVars.ThemeName, "topics", pi, w) } -func route_forum(w http.ResponseWriter, r *http.Request, user User, sfid string){ +func route_forum(w http.ResponseWriter, r *http.Request, user User, sfid string) { page, _ := strconv.Atoi(r.FormValue("page")) // SEO URLs... - halves := strings.Split(sfid,".") + halves := strings.Split(sfid, ".") if len(halves) < 2 { - halves = append(halves,halves[0]) + halves = append(halves, halves[0]) } fid, err := strconv.Atoi(halves[1]) if err != nil { - PreError("The provided ForumID is not a valid number.",w,r) + PreError("The provided ForumID is not a valid number.", w, r) return } - headerVars, ok := ForumSessionCheck(w,r,&user,fid) + headerVars, ok := ForumSessionCheck(w, r, &user, fid) if !ok { return } //log.Printf("groups[user.Group]: %+v\n", groups[user.Group].Forums) if !user.Perms.ViewTopic { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } // TO-DO: Fix this double-check forum, err := fstore.CascadeGet(fid) if err == ErrNoRows { - NotFound(w,r) + NotFound(w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - BuildWidgets("view_forum",forum,&headerVars,r) + BuildWidgets("view_forum", forum, headerVars, r) // Calculate the offset var offset int - last_page := int(forum.TopicCount / config.ItemsPerPage) + 1 + lastPage := (forum.TopicCount / config.ItemsPerPage) + 1 if page > 1 { offset = (config.ItemsPerPage * page) - config.ItemsPerPage } else if page == -1 { - page = last_page + page = lastPage offset = (config.ItemsPerPage * page) - config.ItemsPerPage } else { page = 1 } - rows, err := get_forum_topics_offset_stmt.Query(fid,offset,config.ItemsPerPage) + rows, err := get_forum_topics_offset_stmt.Query(fid, offset, config.ItemsPerPage) if err != nil { - InternalError(err,w) + InternalError(err, w) return } defer rows.Close() // TO-DO: Use something other than TopicsRow as we don't need to store the forum name and link on each and every topic item? var topicList []*TopicsRow - var reqUserList map[int]bool = make(map[int]bool) + var reqUserList = make(map[int]bool) for rows.Next() { - var topicItem TopicsRow = TopicsRow{ID: 0} - err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.Is_Closed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.LastReplyBy, &topicItem.ParentID, &topicItem.PostCount, &topicItem.LikeCount) + var topicItem = TopicsRow{ID: 0} + err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.IsClosed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.LastReplyAt, &topicItem.LastReplyBy, &topicItem.ParentID, &topicItem.PostCount, &topicItem.LikeCount) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - topicItem.Link = build_topic_url(name_to_slug(topicItem.Title),topicItem.ID) - topicItem.LastReplyAt, err = relative_time(topicItem.LastReplyAt) + topicItem.Link = buildTopicURL(nameToSlug(topicItem.Title), topicItem.ID) + topicItem.LastReplyAt, err = relativeTime(topicItem.LastReplyAt) if err != nil { - InternalError(err,w) + InternalError(err, w) } - if hooks["forum_trow_assign"] != nil { - run_vhook("forum_trow_assign", &topicItem, &forum) + if vhooks["forum_trow_assign"] != nil { + runVhook("forum_trow_assign", &topicItem, &forum) } topicList = append(topicList, &topicItem) reqUserList[topicItem.CreatedBy] = true @@ -336,14 +335,14 @@ func route_forum(w http.ResponseWriter, r *http.Request, user User, sfid string) } err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) return } // Convert the user ID map to a slice, then bulk load the users - var idSlice []int = make([]int,len(reqUserList)) + var idSlice = make([]int, len(reqUserList)) var i int - for userID, _ := range reqUserList { + for userID := range reqUserList { idSlice[i] = userID i++ } @@ -351,7 +350,7 @@ func route_forum(w http.ResponseWriter, r *http.Request, user User, sfid string) // TO-DO: What if a user is deleted via the Control Panel? userList, err := users.BulkCascadeGetMap(idSlice) if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -362,30 +361,29 @@ func route_forum(w http.ResponseWriter, r *http.Request, user User, sfid string) topicItem.LastUser = userList[topicItem.LastReplyBy] } - pi := ForumPage{forum.Name,user,headerVars,topicList,*forum,page,last_page,extData} - if pre_render_hooks["pre_render_view_forum"] != nil { - if run_pre_render_hook("pre_render_view_forum", w, r, &user, &pi) { + pi := ForumPage{forum.Name, user, headerVars, topicList, *forum, page, lastPage} + if preRenderHooks["pre_render_view_forum"] != nil { + if runPreRenderHook("pre_render_view_forum", w, r, &user, &pi) { return } } - - template_forum_handle(pi,w) + RunThemeTemplate(headerVars.ThemeName, "forum", pi, w) } -func route_forums(w http.ResponseWriter, r *http.Request, user User){ - headerVars, ok := SessionCheck(w,r,&user) +func route_forums(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } - BuildWidgets("forums",nil,&headerVars,r) + BuildWidgets("forums", nil, headerVars, r) var err error var forumList []Forum var canSee []int - if user.Is_Super_Admin { + if user.IsSuperAdmin { canSee, err = fstore.GetAllIDs() if err != nil { - InternalError(err,w) + InternalError(err, w) return } //log.Print("canSee",canSee) @@ -397,35 +395,34 @@ func route_forums(w http.ResponseWriter, r *http.Request, user User){ for _, fid := range canSee { //log.Print(forums[fid]) - var forum Forum = *fstore.DirtyGet(fid) + var forum = *fstore.DirtyGet(fid) if forum.Active && forum.Name != "" && forum.ParentID == 0 { if forum.LastTopicID != 0 { - forum.LastTopicTime, err = relative_time(forum.LastTopicTime) + forum.LastTopicTime, err = relativeTime(forum.LastTopicTime) if err != nil { - InternalError(err,w) + InternalError(err, w) } } else { forum.LastTopic = "None" forum.LastTopicTime = "" } if hooks["forums_frow_assign"] != nil { - run_hook("forums_frow_assign", &forum) + runHook("forums_frow_assign", &forum) } forumList = append(forumList, forum) } } - pi := ForumsPage{"Forum List",user,headerVars,forumList,extData} - if pre_render_hooks["pre_render_forum_list"] != nil { - if run_pre_render_hook("pre_render_forum_list", w, r, &user, &pi) { + pi := ForumsPage{"Forum List", user, headerVars, forumList} + if preRenderHooks["pre_render_forum_list"] != nil { + if runPreRenderHook("pre_render_forum_list", w, r, &user, &pi) { return } } - - template_forums_handle(pi,w) + RunThemeTemplate(headerVars.ThemeName, "forums", pi, w) } -func route_topic_id(w http.ResponseWriter, r *http.Request, user User){ +func route_topic_id(w http.ResponseWriter, r *http.Request, user User) { var err error var page, offset int var replyList []Reply @@ -433,50 +430,50 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){ page, _ = strconv.Atoi(r.FormValue("page")) // SEO URLs... - halves := strings.Split(r.URL.Path[len("/topic/"):],".") + halves := strings.Split(r.URL.Path[len("/topic/"):], ".") if len(halves) < 2 { - halves = append(halves,halves[0]) + halves = append(halves, halves[0]) } tid, err := strconv.Atoi(halves[1]) if err != nil { - PreError("The provided TopicID is not a valid number.",w,r) + PreError("The provided TopicID is not a valid number.", w, r) return } // Get the topic... - topic, err := get_topicuser(tid) + topic, err := getTopicuser(tid) if err == ErrNoRows { - NotFound(w,r) + NotFound(w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } topic.ClassName = "" - headerVars, ok := ForumSessionCheck(w,r,&user,topic.ParentID) + headerVars, ok := ForumSessionCheck(w, r, &user, topic.ParentID) if !ok { return } if !user.Perms.ViewTopic { //log.Printf("user.Perms: %+v\n", user.Perms) - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } - BuildWidgets("view_topic",&topic,&headerVars,r) + BuildWidgets("view_topic", &topic, headerVars, r) - topic.Content = parse_message(topic.Content) - topic.ContentLines = strings.Count(topic.Content,"\n") + topic.Content = parseMessage(topic.Content) + topic.ContentLines = strings.Count(topic.Content, "\n") // We don't want users posting in locked topics... - if topic.Is_Closed && !user.Is_Mod { + if topic.IsClosed && !user.IsMod { user.Perms.CreateReply = false } topic.Tag = groups[topic.Group].Tag - if groups[topic.Group].Is_Mod || groups[topic.Group].Is_Admin { + if groups[topic.Group].IsMod || groups[topic.Group].IsAdmin { topic.ClassName = config.StaffCss } @@ -491,17 +488,17 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){ } }*/ - topic.CreatedAt, err = relative_time(topic.CreatedAt) + topic.CreatedAt, err = relativeTime(topic.CreatedAt) if err != nil { topic.CreatedAt = "" } // Calculate the offset - last_page := int(topic.PostCount / config.ItemsPerPage) + 1 + lastPage := (topic.PostCount / config.ItemsPerPage) + 1 if page > 1 { offset = (config.ItemsPerPage * page) - config.ItemsPerPage } else if page == -1 { - page = last_page + page = lastPage offset = (config.ItemsPerPage * page) - config.ItemsPerPage } else { page = 1 @@ -510,28 +507,28 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){ // Get the replies.. rows, err := get_topic_replies_offset_stmt.Query(topic.ID, offset, config.ItemsPerPage) if err == ErrNoRows { - LocalError("Bad Page. Some of the posts may have been deleted or you got here by directly typing in the page number.",w,r,user) + LocalError("Bad Page. Some of the posts may have been deleted or you got here by directly typing in the page number.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } defer rows.Close() - replyItem := Reply{ClassName:""} + replyItem := Reply{ClassName: ""} for rows.Next() { - err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &replyItem.Group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IpAddress, &replyItem.LikeCount, &replyItem.ActionType) + err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &replyItem.Group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IPAddress, &replyItem.LikeCount, &replyItem.ActionType) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - replyItem.UserLink = build_profile_url(name_to_slug(replyItem.CreatedByName),replyItem.CreatedBy) + replyItem.UserLink = buildProfileURL(nameToSlug(replyItem.CreatedByName), replyItem.CreatedBy) replyItem.ParentID = topic.ID - replyItem.ContentHtml = parse_message(replyItem.Content) - replyItem.ContentLines = strings.Count(replyItem.Content,"\n") + replyItem.ContentHtml = parseMessage(replyItem.Content) + replyItem.ContentLines = strings.Count(replyItem.Content, "\n") - if groups[replyItem.Group].Is_Mod || groups[replyItem.Group].Is_Admin { + if groups[replyItem.Group].IsMod || groups[replyItem.Group].IsAdmin { replyItem.ClassName = config.StaffCss } else { replyItem.ClassName = "" @@ -542,7 +539,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){ replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar } } else { - replyItem.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(replyItem.CreatedBy),1) + replyItem.Avatar = strings.Replace(config.Noavatar, "{id}", strconv.Itoa(replyItem.CreatedBy), 1) } replyItem.Tag = groups[replyItem.Group].Tag @@ -558,57 +555,56 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){ } }*/ - replyItem.CreatedAt, err = relative_time(replyItem.CreatedAt) + replyItem.CreatedAt, err = relativeTime(replyItem.CreatedAt) if err != nil { replyItem.CreatedAt = "" } // We really shouldn't have inline HTML, we should do something about this... if replyItem.ActionType != "" { - switch(replyItem.ActionType) { - case "lock": - replyItem.ActionType = "This topic has been locked by " + replyItem.CreatedByName + "" - replyItem.ActionIcon = "🔒︎" - case "unlock": - replyItem.ActionType = "This topic has been reopened by " + replyItem.CreatedByName + "" - replyItem.ActionIcon = "🔓︎" - case "stick": - replyItem.ActionType = "This topic has been pinned by " + replyItem.CreatedByName + "" - replyItem.ActionIcon = "📌︎" - case "unstick": - replyItem.ActionType = "This topic has been unpinned by " + replyItem.CreatedByName + "" - replyItem.ActionIcon = "📌︎" - default: - replyItem.ActionType = replyItem.ActionType + " has happened" - replyItem.ActionIcon = "" + switch replyItem.ActionType { + case "lock": + replyItem.ActionType = "This topic has been locked by " + replyItem.CreatedByName + "" + replyItem.ActionIcon = "🔒︎" + case "unlock": + replyItem.ActionType = "This topic has been reopened by " + replyItem.CreatedByName + "" + replyItem.ActionIcon = "🔓︎" + case "stick": + replyItem.ActionType = "This topic has been pinned by " + replyItem.CreatedByName + "" + replyItem.ActionIcon = "📌︎" + case "unstick": + replyItem.ActionType = "This topic has been unpinned by " + replyItem.CreatedByName + "" + replyItem.ActionIcon = "📌︎" + default: + replyItem.ActionType = replyItem.ActionType + " has happened" + replyItem.ActionIcon = "" } } replyItem.Liked = false // TO-DO: Rename this to topic_rrow_assign if hooks["rrow_assign"] != nil { - run_hook("rrow_assign", &replyItem) + runHook("rrow_assign", &replyItem) } replyList = append(replyList, replyItem) } err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) return } - tpage := TopicPage{topic.Title,user,headerVars,replyList,topic,page,last_page,extData} - if pre_render_hooks["pre_render_view_topic"] != nil { - if run_pre_render_hook("pre_render_view_topic", w, r, &user, &tpage) { + tpage := TopicPage{topic.Title, user, headerVars, replyList, topic, page, lastPage} + if preRenderHooks["pre_render_view_topic"] != nil { + if runPreRenderHook("pre_render_view_topic", w, r, &user, &tpage) { return } } - - template_topic_handle(tpage,w) + RunThemeTemplate(headerVars.ThemeName, "topic", tpage, w) } -func route_profile(w http.ResponseWriter, r *http.Request, user User){ - headerVars, ok := SessionCheck(w,r,&user) +func route_profile(w http.ResponseWriter, r *http.Request, user User) { + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } @@ -619,29 +615,29 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){ var replyList []Reply // SEO URLs... - halves := strings.Split(r.URL.Path[len("/user/"):],".") + halves := strings.Split(r.URL.Path[len("/user/"):], ".") if len(halves) < 2 { - halves = append(halves,halves[0]) + halves = append(halves, halves[0]) } pid, err := strconv.Atoi(halves[1]) if err != nil { - LocalError("The provided User ID is not a valid number.",w,r,user) + LocalError("The provided User ID is not a valid number.", w, r, user) return } var puser *User if pid == user.ID { - user.Is_Mod = true + user.IsMod = true puser = &user } else { // Fetch the user data puser, err = users.CascadeGet(pid) if err == ErrNoRows { - NotFound(w,r) + NotFound(w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } } @@ -649,7 +645,7 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){ // Get the replies.. rows, err := get_profile_replies_stmt.Query(puser.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } defer rows.Close() @@ -657,12 +653,12 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){ for rows.Next() { err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &replyGroup) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - replyLines = strings.Count(replyContent,"\n") - if groups[replyGroup].Is_Mod || groups[replyGroup].Is_Admin { + replyLines = strings.Count(replyContent, "\n") + if groups[replyGroup].IsMod || groups[replyGroup].IsAdmin { replyClassName = config.StaffCss } else { replyClassName = "" @@ -672,7 +668,7 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){ replyAvatar = "/uploads/avatar_" + strconv.Itoa(replyCreatedBy) + replyAvatar } } else { - replyAvatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(replyCreatedBy),1) + replyAvatar = strings.Replace(config.Noavatar, "{id}", strconv.Itoa(replyCreatedBy), 1) } if groups[replyGroup].Tag != "" { @@ -688,59 +684,59 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){ // TO-DO: Add a hook here - replyList = append(replyList, Reply{rid,puser.ID,replyContent,parse_message(replyContent),replyCreatedBy,build_profile_url(name_to_slug(replyCreatedByName),replyCreatedBy),replyCreatedByName,replyGroup,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyClassName,replyLines,replyTag,"","","",0,"",replyLiked,replyLikeCount,"",""}) + replyList = append(replyList, Reply{rid, puser.ID, replyContent, parseMessage(replyContent), replyCreatedBy, buildProfileURL(nameToSlug(replyCreatedByName), replyCreatedBy), replyCreatedByName, replyGroup, replyCreatedAt, replyLastEdit, replyLastEditBy, replyAvatar, replyClassName, replyLines, replyTag, "", "", "", 0, "", replyLiked, replyLikeCount, "", ""}) } err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) return } - ppage := ProfilePage{puser.Name + "'s Profile",user,headerVars,replyList,*puser,extData} - if pre_render_hooks["pre_render_profile"] != nil { - if run_pre_render_hook("pre_render_profile", w, r, &user, &ppage) { + ppage := ProfilePage{puser.Name + "'s Profile", user, headerVars, replyList, *puser} + if preRenderHooks["pre_render_profile"] != nil { + if runPreRenderHook("pre_render_profile", w, r, &user, &ppage) { return } } - template_profile_handle(ppage,w) + template_profile_handle(ppage, w) } -func route_topic_create(w http.ResponseWriter, r *http.Request, user User, sfid string){ +func route_topic_create(w http.ResponseWriter, r *http.Request, user User, sfid string) { var fid int var err error if sfid != "" { fid, err = strconv.Atoi(sfid) if err != nil { - PreError("The provided ForumID is not a valid number.",w,r) + PreError("The provided ForumID is not a valid number.", w, r) return } } - headerVars, ok := ForumSessionCheck(w,r,&user,fid) + headerVars, ok := ForumSessionCheck(w, r, &user, fid) if !ok { return } if !user.Loggedin || !user.Perms.CreateTopic { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } - BuildWidgets("create_topic",nil,&headerVars,r) + BuildWidgets("create_topic", nil, headerVars, r) // Lock this to the forum being linked? // Should we always put it in strictmode when it's linked from another forum? Well, the user might end up changing their mind on what forum they want to post in and it would be a hassle, if they had to switch pages, even if it is a single click for many (exc. mobile) var strictmode bool if vhooks["topic_create_pre_loop"] != nil { - run_vhook("topic_create_pre_loop", w, r, fid, &headerVars, &user, &strictmode) + runVhook("topic_create_pre_loop", w, r, fid, &headerVars, &user, &strictmode) } var forumList []Forum var canSee []int - if user.Is_Super_Admin { + if user.IsSuperAdmin { canSee, err = fstore.GetAllIDs() if err != nil { - InternalError(err,w) + InternalError(err, w) return } } else { @@ -761,7 +757,7 @@ func route_topic_create(w http.ResponseWriter, r *http.Request, user User, sfid fcopy := *forum if hooks["topic_create_frow_assign"] != nil { // TO-DO: Add the skip feature to all the other row based hooks? - if run_hook("topic_create_frow_assign", &fcopy).(bool) { + if runHook("topic_create_frow_assign", &fcopy).(bool) { continue } } @@ -769,175 +765,177 @@ func route_topic_create(w http.ResponseWriter, r *http.Request, user User, sfid } } - ctpage := CreateTopicPage{"Create Topic",user,headerVars,forumList,fid,extData} - if pre_render_hooks["pre_render_create_topic"] != nil { - if run_pre_render_hook("pre_render_create_topic", w, r, &user, &ctpage) { + ctpage := CreateTopicPage{"Create Topic", user, headerVars, forumList, fid} + if preRenderHooks["pre_render_create_topic"] != nil { + if runPreRenderHook("pre_render_create_topic", w, r, &user, &ctpage) { return } } - template_create_topic_handle(ctpage,w) + template_create_topic_handle(ctpage, w) } // POST functions. Authorised users only. func route_topic_create_submit(w http.ResponseWriter, r *http.Request, user User) { err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } fid, err := strconv.Atoi(r.PostFormValue("topic-board")) if err != nil { - PreError("The provided ForumID is not a valid number.",w,r) + PreError("The provided ForumID is not a valid number.", w, r) return } - ok := SimpleForumSessionCheck(w,r,&user,fid) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, fid) if !ok { return } if !user.Loggedin || !user.Perms.CreateTopic { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } topic_name := html.EscapeString(r.PostFormValue("topic-name")) - content := html.EscapeString(preparse_message(r.PostFormValue("topic-content"))) + content := html.EscapeString(preparseMessage(r.PostFormValue("topic-content"))) ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - wcount := word_count(content) - res, err := create_topic_stmt.Exec(fid,topic_name,content,parse_message(content),user.ID,ipaddress,wcount,user.ID) + wcount := wordCount(content) + res, err := create_topic_stmt.Exec(fid, topic_name, content, parseMessage(content), user.ID, ipaddress, wcount, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - lastId, err := res.LastInsertId() + lastID, err := res.LastInsertId() if err != nil { - InternalError(err,w) + InternalError(err, w) return } err = fstore.IncrementTopicCount(fid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = add_subscription_stmt.Exec(user.ID,lastId,"topic") + _, err = add_subscription_stmt.Exec(user.ID, lastID, "topic") if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/topic/" + strconv.FormatInt(lastId,10), http.StatusSeeOther) - err = increase_post_user_stats(wcount,user.ID,true,user) + http.Redirect(w, r, "/topic/"+strconv.FormatInt(lastID, 10), http.StatusSeeOther) + err = increase_post_user_stats(wcount, user.ID, true, user) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - err = fstore.UpdateLastTopic(topic_name,int(lastId),user.Name,user.ID,time.Now().Format("2006-01-02 15:04:05"),fid) + err = fstore.UpdateLastTopic(topic_name, int(lastID), user.Name, user.ID, time.Now().Format("2006-01-02 15:04:05"), fid) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) } } func route_create_reply(w http.ResponseWriter, r *http.Request, user User) { err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } tid, err := strconv.Atoi(r.PostFormValue("tid")) if err != nil { - PreError("Failed to convert the Topic ID",w,r) + PreError("Failed to convert the Topic ID", w, r) return } topic, err := topics.CascadeGet(tid) if err == ErrNoRows { - PreError("Couldn't find the parent topic",w,r) + PreError("Couldn't find the parent topic", w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - ok := SimpleForumSessionCheck(w,r,&user,topic.ParentID) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, topic.ParentID) if !ok { return } if !user.Loggedin || !user.Perms.CreateReply { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } - content := preparse_message(html.EscapeString(r.PostFormValue("reply-content"))) + content := preparseMessage(html.EscapeString(r.PostFormValue("reply-content"))) ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - wcount := word_count(content) - _, err = create_reply_stmt.Exec(tid,content,parse_message(content),ipaddress,wcount,user.ID) + wcount := wordCount(content) + _, err = create_reply_stmt.Exec(tid, content, parseMessage(content), ipaddress, wcount, user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = add_replies_to_topic_stmt.Exec(1,user.ID,tid) + _, err = add_replies_to_topic_stmt.Exec(1, user.ID, tid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - err = fstore.UpdateLastTopic(topic.Title,tid,user.Name,user.ID,time.Now().Format("2006-01-02 15:04:05"),topic.ParentID) + err = fstore.UpdateLastTopic(topic.Title, tid, user.Name, user.ID, time.Now().Format("2006-01-02 15:04:05"), topic.ParentID) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } - res, err := add_activity_stmt.Exec(user.ID,topic.CreatedBy,"reply","topic",tid) + res, err := add_activity_stmt.Exec(user.ID, topic.CreatedBy, "reply", "topic", tid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - lastId, err := res.LastInsertId() + lastID, err := res.LastInsertId() if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = notify_watchers_stmt.Exec(lastId) + _, err = notify_watchers_stmt.Exec(lastID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } // Alert the subscribers about this post without blocking this post from being posted - if enable_websockets { - go notify_watchers(lastId) + if enableWebsockets { + go notifyWatchers(lastID) } // Reload the topic... err = topics.Load(tid) if err != nil && err == ErrNoRows { - LocalError("The destination no longer exists",w,r,user) + LocalError("The destination no longer exists", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/topic/" + strconv.Itoa(tid), http.StatusSeeOther) + http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther) err = increase_post_user_stats(wcount, user.ID, false, user) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } @@ -945,268 +943,270 @@ func route_create_reply(w http.ResponseWriter, r *http.Request, user User) { func route_like_topic(w http.ResponseWriter, r *http.Request, user User) { err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } tid, err := strconv.Atoi(r.URL.Path[len("/topic/like/submit/"):]) if err != nil { - PreError("Topic IDs can only ever be numbers.",w,r) + PreError("Topic IDs can only ever be numbers.", w, r) return } topic, err := topics.CascadeGet(tid) if err == ErrNoRows { - PreError("The requested topic doesn't exist.",w,r) + PreError("The requested topic doesn't exist.", w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - ok := SimpleForumSessionCheck(w,r,&user,topic.ParentID) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, topic.ParentID) if !ok { return } if !user.Perms.ViewTopic || !user.Perms.LikeItem { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if topic.CreatedBy == user.ID { - LocalError("You can't like your own topics",w,r,user) + LocalError("You can't like your own topics", w, r, user) return } - err = has_liked_topic_stmt.QueryRow(user.ID,tid).Scan(&tid) + err = has_liked_topic_stmt.QueryRow(user.ID, tid).Scan(&tid) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } else if err != ErrNoRows { - LocalError("You already liked this!",w,r,user) + LocalError("You already liked this!", w, r, user) return } _, err = users.CascadeGet(topic.CreatedBy) if err != nil && err == ErrNoRows { - LocalError("The target user doesn't exist",w,r,user) + LocalError("The target user doesn't exist", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } score := 1 - _, err = create_like_stmt.Exec(score,tid,"topics",user.ID) + _, err = create_like_stmt.Exec(score, tid, "topics", user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = add_likes_to_topic_stmt.Exec(1,tid) + _, err = add_likes_to_topic_stmt.Exec(1, tid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - res, err := add_activity_stmt.Exec(user.ID,topic.CreatedBy,"like","topic",tid) + res, err := add_activity_stmt.Exec(user.ID, topic.CreatedBy, "like", "topic", tid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - lastId, err := res.LastInsertId() + lastID, err := res.LastInsertId() if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = notify_one_stmt.Exec(topic.CreatedBy,lastId) + _, err = notify_one_stmt.Exec(topic.CreatedBy, lastID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } // Live alerts, if the poster is online and WebSockets is enabled - _ = ws_hub.push_alert(topic.CreatedBy,int(lastId),"like","topic",user.ID,topic.CreatedBy,tid) + _ = wsHub.pushAlert(topic.CreatedBy, int(lastID), "like", "topic", user.ID, topic.CreatedBy, tid) // Reload the topic... err = topics.Load(tid) if err != nil && err == ErrNoRows { - LocalError("The liked topic no longer exists",w,r,user) + LocalError("The liked topic no longer exists", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) + http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther) } func route_reply_like_submit(w http.ResponseWriter, r *http.Request, user User) { err := r.ParseForm() if err != nil { - PreError("Bad Form",w,r) + PreError("Bad Form", w, r) return } rid, err := strconv.Atoi(r.URL.Path[len("/reply/like/submit/"):]) if err != nil { - PreError("The provided Reply ID is not a valid number.",w,r) + PreError("The provided Reply ID is not a valid number.", w, r) return } - reply, err := get_reply(rid) + reply, err := getReply(rid) if err == ErrNoRows { - PreError("You can't like something which doesn't exist!",w,r) + PreError("You can't like something which doesn't exist!", w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } var fid int err = get_topic_fid_stmt.QueryRow(reply.ParentID).Scan(&fid) if err == ErrNoRows { - PreError("The parent topic doesn't exist.",w,r) + PreError("The parent topic doesn't exist.", w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - ok := SimpleForumSessionCheck(w,r,&user,fid) + // TO-DO: Add hooks to make use of headerLite + _, ok := SimpleForumSessionCheck(w, r, &user, fid) if !ok { return } if !user.Perms.ViewTopic || !user.Perms.LikeItem { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } if reply.CreatedBy == user.ID { - LocalError("You can't like your own replies",w,r,user) + LocalError("You can't like your own replies", w, r, user) return } err = has_liked_reply_stmt.QueryRow(user.ID, rid).Scan(&rid) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } else if err != ErrNoRows { - LocalError("You already liked this!",w,r,user) + LocalError("You already liked this!", w, r, user) return } _, err = users.CascadeGet(reply.CreatedBy) if err != nil && err != ErrNoRows { - LocalError("The target user doesn't exist",w,r,user) + LocalError("The target user doesn't exist", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } score := 1 - _, err = create_like_stmt.Exec(score,rid,"replies",user.ID) + _, err = create_like_stmt.Exec(score, rid, "replies", user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = add_likes_to_reply_stmt.Exec(1,rid) + _, err = add_likes_to_reply_stmt.Exec(1, rid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - res, err := add_activity_stmt.Exec(user.ID,reply.CreatedBy,"like","post",rid) + res, err := add_activity_stmt.Exec(user.ID, reply.CreatedBy, "like", "post", rid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - lastId, err := res.LastInsertId() + lastID, err := res.LastInsertId() if err != nil { - InternalError(err,w) + InternalError(err, w) return } - _, err = notify_one_stmt.Exec(reply.CreatedBy,lastId) + _, err = notify_one_stmt.Exec(reply.CreatedBy, lastID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } // Live alerts, if the poster is online and WebSockets is enabled - _ = ws_hub.push_alert(reply.CreatedBy,int(lastId),"like","post",user.ID,reply.CreatedBy,rid) + _ = wsHub.pushAlert(reply.CreatedBy, int(lastID), "like", "post", user.ID, reply.CreatedBy, rid) - http.Redirect(w,r,"/topic/" + strconv.Itoa(reply.ParentID),http.StatusSeeOther) + http.Redirect(w, r, "/topic/"+strconv.Itoa(reply.ParentID), http.StatusSeeOther) } func route_profile_reply_create(w http.ResponseWriter, r *http.Request, user User) { if !user.Loggedin || !user.Perms.CreateReply { - NoPermissions(w,r,user) + NoPermissions(w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } uid, err := strconv.Atoi(r.PostFormValue("uid")) if err != nil { - LocalError("Invalid UID",w,r,user) + LocalError("Invalid UID", w, r, user) return } ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - LocalError("Bad IP",w,r,user) + LocalError("Bad IP", w, r, user) return } - _, err = create_profile_reply_stmt.Exec(uid,html.EscapeString(preparse_message(r.PostFormValue("reply-content"))),parse_message(html.EscapeString(preparse_message(r.PostFormValue("reply-content")))),user.ID,ipaddress) + _, err = create_profile_reply_stmt.Exec(uid, html.EscapeString(preparseMessage(r.PostFormValue("reply-content"))), parseMessage(html.EscapeString(preparseMessage(r.PostFormValue("reply-content")))), user.ID, ipaddress) if err != nil { - InternalError(err,w) + InternalError(err, w) return } var user_name string err = get_user_name_stmt.QueryRow(uid).Scan(&user_name) if err == ErrNoRows { - LocalError("The profile you're trying to post on doesn't exist.",w,r,user) + LocalError("The profile you're trying to post on doesn't exist.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w, r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther) + http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther) } func route_report_submit(w http.ResponseWriter, r *http.Request, user User, sitem_id string) { if !user.Loggedin { - LoginRequired(w,r,user) + LoginRequired(w, r, user) return } - if user.Is_Banned { - Banned(w,r,user) + if user.IsBanned { + Banned(w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } if r.FormValue("session") != user.Session { - SecurityError(w,r,user) + SecurityError(w, r, user) return } item_id, err := strconv.Atoi(sitem_id) if err != nil { - LocalError("Bad ID",w,r,user) + LocalError("Bad ID", w, r, user) return } @@ -1215,225 +1215,225 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, user User, site var fid int = 1 var title, content string if item_type == "reply" { - reply, err := get_reply(item_id) + reply, err := getReply(item_id) if err == ErrNoRows { - LocalError("We were unable to find the reported post",w,r,user) + LocalError("We were unable to find the reported post", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } topic, err := topics.CascadeGet(reply.ParentID) if err == ErrNoRows { - LocalError("We weren't able to find the topic the reported post is supposed to be in",w,r,user) + LocalError("We weren't able to find the topic the reported post is supposed to be in", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } title = "Reply: " + topic.Title content = reply.Content + "\n\nOriginal Post: #rid-" + strconv.Itoa(item_id) } else if item_type == "user-reply" { - user_reply, err := get_user_reply(item_id) + userReply, err := getUserReply(item_id) if err == ErrNoRows { - LocalError("We weren't able to find the reported post",w,r,user) + LocalError("We weren't able to find the reported post", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - err = get_user_name_stmt.QueryRow(user_reply.ParentID).Scan(&title) + err = get_user_name_stmt.QueryRow(userReply.ParentID).Scan(&title) if err == ErrNoRows { - LocalError("We weren't able to find the profile the reported post is supposed to be on",w,r,user) + LocalError("We weren't able to find the profile the reported post is supposed to be on", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } title = "Profile: " + title - content = user_reply.Content + "\n\nOriginal Post: @" + strconv.Itoa(user_reply.ParentID) + content = userReply.Content + "\n\nOriginal Post: @" + strconv.Itoa(userReply.ParentID) } else if item_type == "topic" { - err = get_topic_basic_stmt.QueryRow(item_id).Scan(&title,&content) + err = get_topic_basic_stmt.QueryRow(item_id).Scan(&title, &content) if err == ErrNoRows { - NotFound(w,r) + NotFound(w, r) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } title = "Topic: " + title content = content + "\n\nOriginal Post: #tid-" + strconv.Itoa(item_id) } else { if vhooks["report_preassign"] != nil { - run_vhook_noreturn("report_preassign", &item_id, &item_type) + runVhookNoreturn("report_preassign", &item_id, &item_type) return } // Don't try to guess the type - LocalError("Unknown type",w,r,user) + LocalError("Unknown type", w, r, user) return } var count int rows, err := report_exists_stmt.Query(item_type + "_" + strconv.Itoa(item_id)) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } for rows.Next() { err = rows.Scan(&count) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } if count != 0 { - LocalError("Someone has already reported this!",w,r,user) + LocalError("Someone has already reported this!", w, r, user) return } - res, err := create_report_stmt.Exec(title,content,parse_message(content),user.ID,item_type + "_" + strconv.Itoa(item_id)) + res, err := create_report_stmt.Exec(title, content, parseMessage(content), user.ID, item_type+"_"+strconv.Itoa(item_id)) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - lastId, err := res.LastInsertId() + lastID, err := res.LastInsertId() if err != nil { - InternalError(err,w) + InternalError(err, w) return } _, err = add_topics_to_forum_stmt.Exec(1, fid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - err = fstore.UpdateLastTopic(title,int(lastId),user.Name,user.ID,time.Now().Format("2006-01-02 15:04:05"),fid) + err = fstore.UpdateLastTopic(title, int(lastID), user.Name, user.ID, time.Now().Format("2006-01-02 15:04:05"), fid) if err != nil && err != ErrNoRows { - InternalError(err,w) + InternalError(err, w) return } - http.Redirect(w,r,"/topic/" + strconv.FormatInt(lastId, 10), http.StatusSeeOther) + http.Redirect(w, r, "/topic/"+strconv.FormatInt(lastID, 10), http.StatusSeeOther) } func route_account_own_edit_critical(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if !user.Loggedin { - LocalError("You need to login to edit your account.",w,r,user) + LocalError("You need to login to edit your account.", w, r, user) return } - pi := Page{"Edit Password",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_account_own_edit_critical"] != nil { - if run_pre_render_hook("pre_render_account_own_edit_critical", w, r, &user, &pi) { + pi := Page{"Edit Password", user, headerVars, tList, nil} + if preRenderHooks["pre_render_account_own_edit_critical"] != nil { + if runPreRenderHook("pre_render_account_own_edit_critical", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"account-own-edit.html", pi) + templates.ExecuteTemplate(w, "account-own-edit.html", pi) } func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if !user.Loggedin { - LocalError("You need to login to edit your account.",w,r,user) + LocalError("You need to login to edit your account.", w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } - var real_password, salt string - current_password := r.PostFormValue("account-current-password") - new_password := r.PostFormValue("account-new-password") - confirm_password := r.PostFormValue("account-confirm-password") + var realPassword, salt string + currentPassword := r.PostFormValue("account-current-password") + newPassword := r.PostFormValue("account-new-password") + confirmPassword := r.PostFormValue("account-confirm-password") - err = get_password_stmt.QueryRow(user.ID).Scan(&real_password, &salt) + err = get_password_stmt.QueryRow(user.ID).Scan(&realPassword, &salt) if err == ErrNoRows { - LocalError("Your account no longer exists.",w,r,user) + LocalError("Your account no longer exists.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - err = CheckPassword(real_password,current_password,salt) + err = CheckPassword(realPassword, currentPassword, salt) if err == ErrMismatchedHashAndPassword { - LocalError("That's not the correct password.",w,r,user) + LocalError("That's not the correct password.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } - if new_password != confirm_password { - LocalError("The two passwords don't match.",w,r,user) + if newPassword != confirmPassword { + LocalError("The two passwords don't match.", w, r, user) return } - SetPassword(user.ID, new_password) + SetPassword(user.ID, newPassword) // Log the user out as a safety precaution auth.ForceLogout(user.ID) - headerVars.NoticeList = append(headerVars.NoticeList,"Your password was successfully updated") - pi := Page{"Edit Password",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_account_own_edit_critical"] != nil { - if run_pre_render_hook("pre_render_account_own_edit_critical", w, r, &user, &pi) { + headerVars.NoticeList = append(headerVars.NoticeList, "Your password was successfully updated") + pi := Page{"Edit Password", user, headerVars, tList, nil} + if preRenderHooks["pre_render_account_own_edit_critical"] != nil { + if runPreRenderHook("pre_render_account_own_edit_critical", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"account-own-edit.html", pi) + templates.ExecuteTemplate(w, "account-own-edit.html", pi) } func route_account_own_edit_avatar(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if !user.Loggedin { - LocalError("You need to login to edit your account.",w,r,user) + LocalError("You need to login to edit your account.", w, r, user) return } - pi := Page{"Edit Avatar",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_account_own_edit_avatar"] != nil { - if run_pre_render_hook("pre_render_account_own_edit_avatar", w, r, &user, &pi) { + pi := Page{"Edit Avatar", user, headerVars, tList, nil} + if preRenderHooks["pre_render_account_own_edit_avatar"] != nil { + if runPreRenderHook("pre_render_account_own_edit_avatar", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"account-own-edit-avatar.html",pi) + templates.ExecuteTemplate(w, "account-own-edit-avatar.html", pi) } func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request, user User) { if r.ContentLength > int64(config.MaxRequestSize) { - http.Error(w,"Request too large",http.StatusExpectationFailed) + http.Error(w, "Request too large", http.StatusExpectationFailed) return } r.Body = http.MaxBytesReader(w, r.Body, int64(config.MaxRequestSize)) - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if !user.Loggedin { - LocalError("You need to login to edit your account.",w,r,user) + LocalError("You need to login to edit your account.", w, r, user) return } err := r.ParseMultipartForm(int64(config.MaxRequestSize)) - if err != nil { - LocalError("Upload failed",w,r,user) + if err != nil { + LocalError("Upload failed", w, r, user) return } @@ -1441,7 +1441,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request var ext string for _, fheaders := range r.MultipartForm.File { for _, hdr := range fheaders { - infile, err := hdr.Open(); + infile, err := hdr.Open() if err != nil { LocalError("Upload failed", w, r, user) return @@ -1460,123 +1460,123 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request } if ext == "" { - extarr := strings.Split(hdr.Filename,".") + extarr := strings.Split(hdr.Filename, ".") if len(extarr) < 2 { LocalError("Bad file", w, r, user) return } - ext = extarr[len(extarr) - 1] + ext = extarr[len(extarr)-1] reg, err := regexp.Compile("[^A-Za-z0-9]+") if err != nil { LocalError("Bad file extension", w, r, user) return } - ext = reg.ReplaceAllString(ext,"") + ext = reg.ReplaceAllString(ext, "") ext = strings.ToLower(ext) } - outfile, err := os.Create("./uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext); - if err != nil { - LocalError("Upload failed [File Creation Failed]",w,r,user) + outfile, err := os.Create("./uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext) + if err != nil { + LocalError("Upload failed [File Creation Failed]", w, r, user) return } defer outfile.Close() - _, err = io.Copy(outfile, infile); - if err != nil { - LocalError("Upload failed [Copy Failed]",w,r,user) + _, err = io.Copy(outfile, infile) + if err != nil { + LocalError("Upload failed [Copy Failed]", w, r, user) return } } } - _, err = set_avatar_stmt.Exec("." + ext, strconv.Itoa(user.ID)) + _, err = set_avatar_stmt.Exec("."+ext, strconv.Itoa(user.ID)) if err != nil { - InternalError(err,w) + InternalError(err, w) return } user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext err = users.Load(user.ID) if err != nil { - LocalError("This user no longer exists!",w,r,user) + LocalError("This user no longer exists!", w, r, user) return } headerVars.NoticeList = append(headerVars.NoticeList, "Your avatar was successfully updated") - pi := Page{"Edit Avatar",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_account_own_edit_avatar"] != nil { - if run_pre_render_hook("pre_render_account_own_edit_avatar", w, r, &user, &pi) { + pi := Page{"Edit Avatar", user, headerVars, tList, nil} + if preRenderHooks["pre_render_account_own_edit_avatar"] != nil { + if runPreRenderHook("pre_render_account_own_edit_avatar", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"account-own-edit-avatar.html", pi) + templates.ExecuteTemplate(w, "account-own-edit-avatar.html", pi) } func route_account_own_edit_username(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if !user.Loggedin { - LocalError("You need to login to edit your account.",w,r,user) + LocalError("You need to login to edit your account.", w, r, user) return } - pi := Page{"Edit Username",user,headerVars,tList,user.Name} - if pre_render_hooks["pre_render_account_own_edit_username"] != nil { - if run_pre_render_hook("pre_render_account_own_edit_username", w, r, &user, &pi) { + pi := Page{"Edit Username", user, headerVars, tList, user.Name} + if preRenderHooks["pre_render_account_own_edit_username"] != nil { + if runPreRenderHook("pre_render_account_own_edit_username", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"account-own-edit-username.html",pi) + templates.ExecuteTemplate(w, "account-own-edit-username.html", pi) } func route_account_own_edit_username_submit(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if !user.Loggedin { - LocalError("You need to login to edit your account.",w,r,user) + LocalError("You need to login to edit your account.", w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } new_username := html.EscapeString(r.PostFormValue("account-new-username")) _, err = set_username_stmt.Exec(new_username, strconv.Itoa(user.ID)) if err != nil { - LocalError("Unable to change the username. Does someone else already have this name?",w,r,user) + LocalError("Unable to change the username. Does someone else already have this name?", w, r, user) return } user.Name = new_username err = users.Load(user.ID) if err != nil { - LocalError("Your account doesn't exist!",w,r,user) + LocalError("Your account doesn't exist!", w, r, user) return } - headerVars.NoticeList = append(headerVars.NoticeList,"Your username was successfully updated") - pi := Page{"Edit Username",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_account_own_edit_username"] != nil { - if run_pre_render_hook("pre_render_account_own_edit_username", w, r, &user, &pi) { + headerVars.NoticeList = append(headerVars.NoticeList, "Your username was successfully updated") + pi := Page{"Edit Username", user, headerVars, tList, nil} + if preRenderHooks["pre_render_account_own_edit_username"] != nil { + if runPreRenderHook("pre_render_account_own_edit_username", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"account-own-edit-username.html", pi) + templates.ExecuteTemplate(w, "account-own-edit-username.html", pi) } func route_account_own_edit_email(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if !user.Loggedin { - LocalError("You need to login to edit your account.",w,r,user) + LocalError("You need to login to edit your account.", w, r, user) return } @@ -1614,24 +1614,24 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request, user U } if !site.EnableEmails { - headerVars.NoticeList = append(headerVars.NoticeList,"The mail system is currently disabled.") + headerVars.NoticeList = append(headerVars.NoticeList, "The mail system is currently disabled.") } - pi := Page{"Email Manager",user,headerVars,emailList,nil} - if pre_render_hooks["pre_render_account_own_edit_email"] != nil { - if run_pre_render_hook("pre_render_account_own_edit_email", w, r, &user, &pi) { + pi := Page{"Email Manager", user, headerVars, emailList, nil} + if preRenderHooks["pre_render_account_own_edit_email"] != nil { + if runPreRenderHook("pre_render_account_own_edit_email", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"account-own-edit-email.html", pi) + templates.ExecuteTemplate(w, "account-own-edit-email.html", pi) } func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if !user.Loggedin { - LocalError("You need to login to edit your account.",w,r,user) + LocalError("You need to login to edit your account.", w, r, user) return } token := r.URL.Path[len("/user/edit/token/"):] @@ -1641,7 +1641,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re var emailList []interface{} rows, err := get_emails_by_user_stmt.Query(user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } defer rows.Close() @@ -1649,7 +1649,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re for rows.Next() { err := rows.Scan(&email.Email, &email.Validated, &email.Token) if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -1663,22 +1663,22 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re } err = rows.Err() if err != nil { - InternalError(err,w) + InternalError(err, w) return } if len(emailList) == 0 { - LocalError("A verification email was never sent for you!",w,r,user) + LocalError("A verification email was never sent for you!", w, r, user) return } if targetEmail.Token == "" { - LocalError("That's not a valid token!",w,r,user) + LocalError("That's not a valid token!", w, r, user) return } _, err = verify_email_stmt.Exec(user.Email) if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -1686,49 +1686,49 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re if headerVars.Settings["activation_type"] == 2 { _, err = activate_user_stmt.Exec(user.ID) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } if !site.EnableEmails { - headerVars.NoticeList = append(headerVars.NoticeList,"The mail system is currently disabled.") + headerVars.NoticeList = append(headerVars.NoticeList, "The mail system is currently disabled.") } - headerVars.NoticeList = append(headerVars.NoticeList,"Your email was successfully verified") - pi := Page{"Email Manager",user,headerVars,emailList,nil} - if pre_render_hooks["pre_render_account_own_edit_email"] != nil { - if run_pre_render_hook("pre_render_account_own_edit_email", w, r, &user, &pi) { + headerVars.NoticeList = append(headerVars.NoticeList, "Your email was successfully verified") + pi := Page{"Email Manager", user, headerVars, emailList, nil} + if preRenderHooks["pre_render_account_own_edit_email"] != nil { + if runPreRenderHook("pre_render_account_own_edit_email", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"account-own-edit-email.html", pi) + templates.ExecuteTemplate(w, "account-own-edit-email.html", pi) } func route_logout(w http.ResponseWriter, r *http.Request, user User) { if !user.Loggedin { - LocalError("You can't logout without logging in first.",w,r,user) + LocalError("You can't logout without logging in first.", w, r, user) return } auth.Logout(w, user.ID) - http.Redirect(w,r, "/", http.StatusSeeOther) + http.Redirect(w, r, "/", http.StatusSeeOther) } func route_login(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if user.Loggedin { - LocalError("You're already logged in.",w,r,user) + LocalError("You're already logged in.", w, r, user) return } - pi := Page{"Login",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_login"] != nil { - if run_pre_render_hook("pre_render_login", w, r, &user, &pi) { + pi := Page{"Login", user, headerVars, tList, nil} + if preRenderHooks["pre_render_login"] != nil { + if runPreRenderHook("pre_render_login", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"login.html",pi) + templates.ExecuteTemplate(w, "login.html", pi) } // TO-DO: Log failed attempted logins? @@ -1736,24 +1736,24 @@ func route_login(w http.ResponseWriter, r *http.Request, user User) { // TO-DO: Log unusual countries in comparison to the country a user usually logs in from? Alert the user about this? func route_login_submit(w http.ResponseWriter, r *http.Request, user User) { if user.Loggedin { - LocalError("You're already logged in.",w,r,user) + LocalError("You're already logged in.", w, r, user) return } err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } uid, err := auth.Authenticate(html.EscapeString(r.PostFormValue("username")), r.PostFormValue("password")) if err != nil { - LocalError(err.Error(),w,r,user) + LocalError(err.Error(), w, r, user) return } userPtr, err := users.CascadeGet(uid) if err != nil { - LocalError("Bad account",w,r,user) + LocalError("Bad account", w, r, user) return } user = *userPtr @@ -1762,83 +1762,83 @@ func route_login_submit(w http.ResponseWriter, r *http.Request, user User) { if user.Session == "" { session, err = auth.CreateSession(uid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } } else { session = user.Session } - auth.SetCookies(w,uid,session) - if user.Is_Admin { + auth.SetCookies(w, uid, session) + if user.IsAdmin { // Is this error check reundant? We already check for the error in PreRoute for the same IP host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - InternalError(err,w) + InternalError(err, w) return } log.Print("#" + strconv.Itoa(uid) + " has logged in with IP " + host) } - http.Redirect(w,r,"/",http.StatusSeeOther) + http.Redirect(w, r, "/", http.StatusSeeOther) } func route_register(w http.ResponseWriter, r *http.Request, user User) { - headerVars, ok := SessionCheck(w,r,&user) + headerVars, ok := SessionCheck(w, r, &user) if !ok { return } if user.Loggedin { - LocalError("You're already logged in.",w,r,user) + LocalError("You're already logged in.", w, r, user) return } - pi := Page{"Registration",user,headerVars,tList,nil} - if pre_render_hooks["pre_render_register"] != nil { - if run_pre_render_hook("pre_render_register", w, r, &user, &pi) { + pi := Page{"Registration", user, headerVars, tList, nil} + if preRenderHooks["pre_render_register"] != nil { + if runPreRenderHook("pre_render_register", w, r, &user, &pi) { return } } - templates.ExecuteTemplate(w,"register.html",pi) + templates.ExecuteTemplate(w, "register.html", pi) } func route_register_submit(w http.ResponseWriter, r *http.Request, user User) { - headerLite, _ := SimpleSessionCheck(w,r,&user) + headerLite, _ := SimpleSessionCheck(w, r, &user) err := r.ParseForm() if err != nil { - LocalError("Bad Form",w,r,user) + LocalError("Bad Form", w, r, user) return } username := html.EscapeString(r.PostFormValue("username")) if username == "" { - LocalError("You didn't put in a username.",w,r,user) + LocalError("You didn't put in a username.", w, r, user) return } email := html.EscapeString(r.PostFormValue("email")) if email == "" { - LocalError("You didn't put in an email.",w,r,user) + LocalError("You didn't put in an email.", w, r, user) return } password := r.PostFormValue("password") if password == "" { - LocalError("You didn't put in a password.",w,r,user) + LocalError("You didn't put in a password.", w, r, user) return } if password == username { - LocalError("You can't use your username as your password.",w,r,user) + LocalError("You can't use your username as your password.", w, r, user) return } if password == email { - LocalError("You can't use your email as your password.",w,r,user) + LocalError("You can't use your email as your password.", w, r, user) return } - err = weak_password(password) + err = weakPassword(password) if err != nil { - LocalError(err.Error(),w,r,user) + LocalError(err.Error(), w, r, user) return } @@ -1847,25 +1847,25 @@ func route_register_submit(w http.ResponseWriter, r *http.Request, user User) { // Do the two inputted passwords match..? if password != confirm_password { - LocalError("The two passwords don't match.",w,r,user) + LocalError("The two passwords don't match.", w, r, user) return } var active, group int switch headerLite.Settings["activation_type"] { - case 1: // Activate All - active = 1 - group = config.DefaultGroup - default: // Anything else. E.g. Admin Activation or Email Activation. - group = config.ActivationGroup + case 1: // Activate All + active = 1 + group = config.DefaultGroup + default: // Anything else. E.g. Admin Activation or Email Activation. + group = config.ActivationGroup } uid, err := users.CreateUser(username, password, email, group, active) - if err == err_account_exists { - LocalError("This username isn't available. Try another.",w,r,user) + if err == errAccountExists { + LocalError("This username isn't available. Try another.", w, r, user) return } else if err != nil { - InternalError(err,w) + InternalError(err, w) return } @@ -1873,123 +1873,124 @@ func route_register_submit(w http.ResponseWriter, r *http.Request, user User) { if site.EnableEmails { token, err := GenerateSafeString(80) if err != nil { - InternalError(err,w) + InternalError(err, w) return } _, err = add_email_stmt.Exec(email, uid, 0, token) if err != nil { - InternalError(err,w) + InternalError(err, w) return } if !SendValidationEmail(username, email, token) { - LocalError("We were unable to send the email for you to confirm that this email address belongs to you. You may not have access to some functionality until you do so. Please ask an administrator for assistance.",w,r,user) + LocalError("We were unable to send the email for you to confirm that this email address belongs to you. You may not have access to some functionality until you do so. Please ask an administrator for assistance.", w, r, user) return } } session, err := auth.CreateSession(uid) if err != nil { - InternalError(err,w) + InternalError(err, w) return } - auth.SetCookies(w,uid,session) - http.Redirect(w,r,"/",http.StatusSeeOther) + auth.SetCookies(w, uid, session) + http.Redirect(w, r, "/", http.StatusSeeOther) } // TO-DO: We don't need support XML here to support sitemaps, we could handle those elsewhere -var phrase_login_alerts []byte = []byte(`{"msgs":[{"msg":"Login to see your alerts","path":"/accounts/login"}]}`) +var phrase_login_alerts = []byte(`{"msgs":[{"msg":"Login to see your alerts","path":"/accounts/login"}]}`) + func route_api(w http.ResponseWriter, r *http.Request, user User) { - w.Header().Set("Content-Type","application/json") + w.Header().Set("Content-Type", "application/json") err := r.ParseForm() if err != nil { - PreErrorJS("Bad Form",w,r) + PreErrorJS("Bad Form", w, r) return } action := r.FormValue("action") if action != "get" && action != "set" { - PreErrorJS("Invalid Action",w,r) + PreErrorJS("Invalid Action", w, r) return } module := r.FormValue("module") - switch(module) { - case "dismiss-alert": - asid, err := strconv.Atoi(r.FormValue("asid")) + switch module { + case "dismiss-alert": + asid, err := strconv.Atoi(r.FormValue("asid")) + if err != nil { + PreErrorJS("Invalid asid", w, r) + return + } + + _, err = delete_activity_stream_match_stmt.Exec(user.ID, asid) + if err != nil { + InternalError(err, w) + return + } + case "alerts": // A feed of events tailored for a specific user + if !user.Loggedin { + w.Write(phrase_login_alerts) + return + } + + var msglist, event, elementType string + var asid, actorID, targetUserID, elementID int + var msgCount int + + err = get_activity_count_by_watcher_stmt.QueryRow(user.ID).Scan(&msgCount) + if err == ErrNoRows { + PreErrorJS("Couldn't find the parent topic", w, r) + return + } else if err != nil { + InternalErrorJS(err, w, r) + return + } + + rows, err := get_activity_feed_by_watcher_stmt.Query(user.ID) + if err != nil { + InternalErrorJS(err, w, r) + return + } + defer rows.Close() + + for rows.Next() { + err = rows.Scan(&asid, &actorID, &targetUserID, &event, &elementType, &elementID) if err != nil { - PreErrorJS("Invalid asid",w,r) + InternalErrorJS(err, w, r) return } - - _, err = delete_activity_stream_match_stmt.Exec(user.ID,asid) + res, err := buildAlert(asid, event, elementType, actorID, targetUserID, elementID, user) if err != nil { - InternalError(err,w) - return - } - case "alerts": // A feed of events tailored for a specific user - if !user.Loggedin { - w.Write(phrase_login_alerts) + LocalErrorJS(err.Error(), w, r) return } + msglist += res + "," + } - var msglist, event, elementType string - var asid, actor_id, targetUser_id, elementID int - var msgCount int + err = rows.Err() + if err != nil { + InternalErrorJS(err, w, r) + return + } - err = get_activity_count_by_watcher_stmt.QueryRow(user.ID).Scan(&msgCount) - if err == ErrNoRows { - PreErrorJS("Couldn't find the parent topic",w,r) - return - } else if err != nil { - InternalErrorJS(err,w,r) - return - } - - rows, err := get_activity_feed_by_watcher_stmt.Query(user.ID) - if err != nil { - InternalErrorJS(err,w,r) - return - } - defer rows.Close() - - for rows.Next() { - err = rows.Scan(&asid,&actor_id,&targetUser_id,&event,&elementType,&elementID) - if err != nil { - InternalErrorJS(err,w,r) - return - } - res, err := build_alert(asid, event, elementType, actor_id, targetUser_id, elementID, user) - if err != nil { - LocalErrorJS(err.Error(),w,r) - return - } - msglist += res + "," - } - - err = rows.Err() - if err != nil { - InternalErrorJS(err,w,r) - return - } - - if len(msglist) != 0 { - msglist = msglist[0:len(msglist)-1] - } - w.Write([]byte(`{"msgs":[` + msglist + `],"msgCount":` + strconv.Itoa(msgCount) + `}`)) - //log.Print(`{"msgs":[` + msglist + `],"msgCount":` + strconv.Itoa(msgCount) + `}`) - //case "topics": - //case "forums": - //case "users": - //case "pages": - // This might not be possible. We might need .xml paths for sitemaps - /*case "sitemap": - if format != "xml" { - PreError("You can only fetch sitemaps in the XML format!",w,r) - return - }*/ - default: - PreErrorJS("Invalid Module",w,r) + if len(msglist) != 0 { + msglist = msglist[0 : len(msglist)-1] + } + _, _ = w.Write([]byte(`{"msgs":[` + msglist + `],"msgCount":` + strconv.Itoa(msgCount) + `}`)) + //log.Print(`{"msgs":[` + msglist + `],"msgCount":` + strconv.Itoa(msgCount) + `}`) + //case "topics": + //case "forums": + //case "users": + //case "pages": + // This might not be possible. We might need .xml paths for sitemaps + /*case "sitemap": + if format != "xml" { + PreError("You can only fetch sitemaps in the XML format!",w,r) + return + }*/ + default: + PreErrorJS("Invalid Module", w, r) } } diff --git a/setting.go b/setting.go index b0aee067..b026585c 100644 --- a/setting.go +++ b/setting.go @@ -1,31 +1,28 @@ package main + import "strconv" import "strings" import "sync/atomic" -// TO-DO: Move this into the phrase system -var settingLabels map[string]string +// SettingBox is a map type specifically for holding the various settings admins set to toggle features on and off or to otherwise alter Gosora's behaviour from the Control Panel type SettingBox map[string]interface{} + var settingBox atomic.Value // An atomic value pointing to a SettingBox -type OptionLabel struct -{ - Label string - Value int +type OptionLabel struct { + Label string + Value int Selected bool } -type Setting struct -{ - Name string - Content string - Type string +type Setting struct { + Name string + Content string + Type string Constraint string } func init() { - settingLabels = make(map[string]string) - settingLabels["activation_type"] = "Activate All,Email Activation,Admin Approval" settingBox.Store(SettingBox(make(map[string]interface{}))) //settingBox.Store(make(map[string]interface{})) } @@ -76,7 +73,7 @@ func (sBox SettingBox) ParseSetting(sname string, scontent string, stype string, return "You were supposed to enter an integer x.x\nType mismatch in " + sname } } else if stype == "list" { - cons := strings.Split(constraint,"-") + cons := strings.Split(constraint, "-") if len(cons) < 2 { return "Invalid constraint! The second field wasn't set!" } @@ -90,7 +87,7 @@ func (sBox SettingBox) ParseSetting(sname string, scontent string, stype string, return "Invalid contraint! The constraint field wasn't an integer!" } - value, err := strconv.Atoi(scontent) + value, err := strconv.Atoi(scontent) if err != nil { return "Only integers are allowed in this setting x.x\nType mismatch in " + sname } diff --git a/tasks.go b/tasks.go index ee6267b1..02dfd82e 100644 --- a/tasks.go +++ b/tasks.go @@ -2,7 +2,7 @@ package main import "time" -func handle_expired_scheduled_groups() error { +func handleExpiredScheduledGroups() error { rows, err := get_expired_scheduled_groups_stmt.Query() if err != nil { return err @@ -19,7 +19,7 @@ func handle_expired_scheduled_groups() error { if err != nil { return err } - _, err = set_temp_group_stmt.Exec(0,uid) + _, err = set_temp_group_stmt.Exec(0, uid) if err != nil { return err } diff --git a/template_forum.go b/template_forum.go index bfafdf71..2045f858 100644 --- a/template_forum.go +++ b/template_forum.go @@ -6,63 +6,68 @@ package main import "net/http" import "strconv" +// nolint func init() { 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 + tmplPtrMap["forum"] = &template_forum_handle + tmplPtrMap["o_forum"] = template_forum } +// nolint func template_forum(tmpl_forum_vars ForumPage, w http.ResponseWriter) { w.Write(header_0) w.Write([]byte(tmpl_forum_vars.Title)) w.Write(header_1) +w.Write([]byte(tmpl_forum_vars.Header.ThemeName)) +w.Write(header_2) if len(tmpl_forum_vars.Header.Stylesheets) != 0 { for _, item := range tmpl_forum_vars.Header.Stylesheets { -w.Write(header_2) -w.Write([]byte(item)) w.Write(header_3) -} -} +w.Write([]byte(item)) w.Write(header_4) +} +} +w.Write(header_5) if len(tmpl_forum_vars.Header.Scripts) != 0 { for _, item := range tmpl_forum_vars.Header.Scripts { -w.Write(header_5) -w.Write([]byte(item)) w.Write(header_6) -} -} +w.Write([]byte(item)) w.Write(header_7) -w.Write([]byte(tmpl_forum_vars.CurrentUser.Session)) +} +} w.Write(header_8) -if !tmpl_forum_vars.CurrentUser.Is_Super_Mod { -w.Write(header_9) -} -w.Write(header_10) -w.Write(menu_0) -w.Write([]byte(tmpl_forum_vars.Header.Site.Name)) -w.Write(menu_1) -if tmpl_forum_vars.CurrentUser.Loggedin { -w.Write(menu_2) -w.Write([]byte(tmpl_forum_vars.CurrentUser.Link)) -w.Write(menu_3) w.Write([]byte(tmpl_forum_vars.CurrentUser.Session)) -w.Write(menu_4) -} else { -w.Write(menu_5) +w.Write(header_9) +if !tmpl_forum_vars.CurrentUser.IsSuperMod { +w.Write(header_10) } -w.Write(menu_6) w.Write(header_11) -if tmpl_forum_vars.Header.Widgets.RightSidebar != "" { -w.Write(header_12) +w.Write(menu_0) +w.Write(menu_1) +w.Write([]byte(tmpl_forum_vars.Header.Site.Name)) +w.Write(menu_2) +if tmpl_forum_vars.CurrentUser.Loggedin { +w.Write(menu_3) +w.Write([]byte(tmpl_forum_vars.CurrentUser.Link)) +w.Write(menu_4) +w.Write([]byte(tmpl_forum_vars.CurrentUser.Session)) +w.Write(menu_5) +} else { +w.Write(menu_6) } +w.Write(menu_7) +w.Write(header_12) +if tmpl_forum_vars.Header.Widgets.RightSidebar != "" { w.Write(header_13) +} +w.Write(header_14) if len(tmpl_forum_vars.Header.NoticeList) != 0 { for _, item := range tmpl_forum_vars.Header.NoticeList { -w.Write(header_14) -w.Write([]byte(item)) w.Write(header_15) +w.Write([]byte(item)) +w.Write(header_16) } } if tmpl_forum_vars.Page > 1 { @@ -107,7 +112,7 @@ w.Write(forum_17) if item.Sticky { w.Write(forum_18) } else { -if item.Is_Closed { +if item.IsClosed { w.Write(forum_19) } } @@ -130,7 +135,7 @@ w.Write([]byte(item.Creator.Link)) w.Write(forum_28) w.Write([]byte(item.Creator.Name)) w.Write(forum_29) -if item.Is_Closed { +if item.IsClosed { w.Write(forum_30) } if item.Sticky { diff --git a/template_forums.go b/template_forums.go index 397db116..aa36fdb8 100644 --- a/template_forums.go +++ b/template_forums.go @@ -5,63 +5,68 @@ package main import "net/http" +// nolint func init() { 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 + tmplPtrMap["forums"] = &template_forums_handle + tmplPtrMap["o_forums"] = template_forums } +// nolint func template_forums(tmpl_forums_vars ForumsPage, w http.ResponseWriter) { w.Write(header_0) w.Write([]byte(tmpl_forums_vars.Title)) w.Write(header_1) +w.Write([]byte(tmpl_forums_vars.Header.ThemeName)) +w.Write(header_2) if len(tmpl_forums_vars.Header.Stylesheets) != 0 { for _, item := range tmpl_forums_vars.Header.Stylesheets { -w.Write(header_2) -w.Write([]byte(item)) w.Write(header_3) -} -} +w.Write([]byte(item)) w.Write(header_4) +} +} +w.Write(header_5) if len(tmpl_forums_vars.Header.Scripts) != 0 { for _, item := range tmpl_forums_vars.Header.Scripts { -w.Write(header_5) -w.Write([]byte(item)) w.Write(header_6) -} -} +w.Write([]byte(item)) w.Write(header_7) -w.Write([]byte(tmpl_forums_vars.CurrentUser.Session)) +} +} w.Write(header_8) -if !tmpl_forums_vars.CurrentUser.Is_Super_Mod { -w.Write(header_9) -} -w.Write(header_10) -w.Write(menu_0) -w.Write([]byte(tmpl_forums_vars.Header.Site.Name)) -w.Write(menu_1) -if tmpl_forums_vars.CurrentUser.Loggedin { -w.Write(menu_2) -w.Write([]byte(tmpl_forums_vars.CurrentUser.Link)) -w.Write(menu_3) w.Write([]byte(tmpl_forums_vars.CurrentUser.Session)) -w.Write(menu_4) -} else { -w.Write(menu_5) +w.Write(header_9) +if !tmpl_forums_vars.CurrentUser.IsSuperMod { +w.Write(header_10) } -w.Write(menu_6) w.Write(header_11) -if tmpl_forums_vars.Header.Widgets.RightSidebar != "" { -w.Write(header_12) +w.Write(menu_0) +w.Write(menu_1) +w.Write([]byte(tmpl_forums_vars.Header.Site.Name)) +w.Write(menu_2) +if tmpl_forums_vars.CurrentUser.Loggedin { +w.Write(menu_3) +w.Write([]byte(tmpl_forums_vars.CurrentUser.Link)) +w.Write(menu_4) +w.Write([]byte(tmpl_forums_vars.CurrentUser.Session)) +w.Write(menu_5) +} else { +w.Write(menu_6) } +w.Write(menu_7) +w.Write(header_12) +if tmpl_forums_vars.Header.Widgets.RightSidebar != "" { w.Write(header_13) +} +w.Write(header_14) if len(tmpl_forums_vars.Header.NoticeList) != 0 { for _, item := range tmpl_forums_vars.Header.NoticeList { -w.Write(header_14) -w.Write([]byte(item)) w.Write(header_15) +w.Write([]byte(item)) +w.Write(header_16) } } w.Write(forums_0) diff --git a/template_init.go b/template_init.go index a9be0742..c283e73c 100644 --- a/template_init.go +++ b/template_init.go @@ -11,81 +11,81 @@ func interpreted_topic_template(pi TopicPage, w http.ResponseWriter) { if !ok { mapping = "topic" } - err := templates.ExecuteTemplate(w,mapping + ".html", pi) + err := templates.ExecuteTemplate(w, mapping+".html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -var template_topic_handle func(TopicPage,http.ResponseWriter) = interpreted_topic_template -var template_topic_alt_handle func(TopicPage,http.ResponseWriter) = interpreted_topic_template +var template_topic_handle func(TopicPage, http.ResponseWriter) = interpreted_topic_template +var template_topic_alt_handle func(TopicPage, http.ResponseWriter) = interpreted_topic_template -var template_topics_handle func(TopicsPage,http.ResponseWriter) = func(pi TopicsPage, w http.ResponseWriter) { +var template_topics_handle func(TopicsPage, http.ResponseWriter) = func(pi TopicsPage, w http.ResponseWriter) { mapping, ok := themes[defaultTheme].TemplatesMap["topics"] if !ok { mapping = "topics" } - err := templates.ExecuteTemplate(w,mapping + ".html", pi) + err := templates.ExecuteTemplate(w, mapping+".html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -var template_forum_handle func(ForumPage,http.ResponseWriter) = func(pi ForumPage, w http.ResponseWriter) { +var template_forum_handle func(ForumPage, http.ResponseWriter) = func(pi ForumPage, w http.ResponseWriter) { mapping, ok := themes[defaultTheme].TemplatesMap["forum"] if !ok { mapping = "forum" } - err := templates.ExecuteTemplate(w,mapping + ".html", pi) + err := templates.ExecuteTemplate(w, mapping+".html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -var template_forums_handle func(ForumsPage,http.ResponseWriter) = func(pi ForumsPage, w http.ResponseWriter) { +var template_forums_handle func(ForumsPage, http.ResponseWriter) = func(pi ForumsPage, w http.ResponseWriter) { mapping, ok := themes[defaultTheme].TemplatesMap["forums"] if !ok { mapping = "forums" } - err := templates.ExecuteTemplate(w,mapping + ".html", pi) + err := templates.ExecuteTemplate(w, mapping+".html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -var template_profile_handle func(ProfilePage,http.ResponseWriter) = func(pi ProfilePage, w http.ResponseWriter) { +var template_profile_handle func(ProfilePage, http.ResponseWriter) = func(pi ProfilePage, w http.ResponseWriter) { mapping, ok := themes[defaultTheme].TemplatesMap["profile"] if !ok { mapping = "profile" } - err := templates.ExecuteTemplate(w,mapping + ".html", pi) + err := templates.ExecuteTemplate(w, mapping+".html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -var template_create_topic_handle func(CreateTopicPage,http.ResponseWriter) = func(pi CreateTopicPage, w http.ResponseWriter) { +var template_create_topic_handle func(CreateTopicPage, http.ResponseWriter) = func(pi CreateTopicPage, w http.ResponseWriter) { mapping, ok := themes[defaultTheme].TemplatesMap["create-topic"] if !ok { mapping = "create-topic" } - err := templates.ExecuteTemplate(w,mapping + ".html", pi) + err := templates.ExecuteTemplate(w, mapping+".html", pi) if err != nil { - InternalError(err,w) + InternalError(err, w) } } -func compile_templates() error { +func compileTemplates() error { var c CTemplateSet - user := User{62,build_profile_url("fake-user",62),"Fake User","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,make(map[string]bool),"",false,"","","","","",0,0,"0.0.0.0.0",0} + user := User{62, buildProfileURL("fake-user", 62), "Fake User", "compiler@localhost", 0, false, false, false, false, false, false, GuestPerms, make(map[string]bool), "", false, "", "", "", "", "", 0, 0, "0.0.0.0.0", 0} // TO-DO: Do a more accurate level calculation for this? - user2 := User{1,build_profile_url("admin-alice",1),"Admin Alice","alice@localhost",1,true,true,true,true,false,false,AllPerms,make(map[string]bool),"",true,"","","","","",58,1000,"127.0.0.1",0} - user3 := User{2,build_profile_url("admin-fred",62),"Admin Fred","fred@localhost",1,true,true,true,true,false,false,AllPerms,make(map[string]bool),"",true,"","","","","",42,900,"::1",0} - headerVars := HeaderVars{ - Site: site, - NoticeList: []string{"test"}, + user2 := User{1, buildProfileURL("admin-alice", 1), "Admin Alice", "alice@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, "", "", "", "", "", 58, 1000, "127.0.0.1", 0} + user3 := User{2, buildProfileURL("admin-fred", 62), "Admin Fred", "fred@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, "", "", "", "", "", 42, 900, "::1", 0} + headerVars := &HeaderVars{ + Site: site, + NoticeList: []string{"test"}, Stylesheets: []string{"panel"}, - Scripts: []string{"whatever"}, + Scripts: []string{"whatever"}, Widgets: PageWidgets{ LeftSidebar: template.HTML("lalala"), }, @@ -93,24 +93,24 @@ func compile_templates() error { log.Print("Compiling the templates") - topic := TopicUser{1,"blah","Blah","Hey there!",0,false,false,"Date","Date",0,"","127.0.0.1",0,1,"classname","weird-data",build_profile_url("fake-user",62),"Fake User",config.DefaultGroup,"",0,"","","","",58,false} + topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, "Date", "Date", 0, "", "127.0.0.1", 0, 1, "classname", "weird-data", buildProfileURL("fake-user", 62), "Fake User", config.DefaultGroup, "", 0, "", "", "", "", 58, false} var replyList []Reply - replyList = append(replyList, Reply{0,0,"Yo!","Yo!",0,"alice","Alice",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""}) + replyList = append(replyList, Reply{0, 0, "Yo!", "Yo!", 0, "alice", "Alice", config.DefaultGroup, "", 0, 0, "", "", 0, "", "", "", "", 0, "127.0.0.1", false, 1, "", ""}) var varList map[string]VarItem = make(map[string]VarItem) - tpage := TopicPage{"Title",user,headerVars,replyList,topic,1,1,extData} - topic_id_tmpl, err := c.compile_template("topic.html","templates/","TopicPage", tpage, varList) + tpage := TopicPage{"Title", user, headerVars, replyList, topic, 1, 1} + topic_id_tmpl, err := c.compileTemplate("topic.html", "templates/", "TopicPage", tpage, varList) if err != nil { return err } - topic_id_alt_tmpl, err := c.compile_template("topic_alt.html","templates/","TopicPage", tpage, varList) + topic_id_alt_tmpl, err := c.compileTemplate("topic_alt.html", "templates/", "TopicPage", tpage, varList) if err != nil { return err } varList = make(map[string]VarItem) - ppage := ProfilePage{"User 526",user,headerVars,replyList,user,extData} - profile_tmpl, err := c.compile_template("profile.html","templates/","ProfilePage", ppage, varList) + ppage := ProfilePage{"User 526", user, headerVars, replyList, user} + profile_tmpl, err := c.compileTemplate("profile.html", "templates/", "ProfilePage", ppage, varList) if err != nil { return err } @@ -123,42 +123,42 @@ func compile_templates() error { for _, forum := range forums { if forum.Active { - forumList = append(forumList,*forum) + forumList = append(forumList, *forum) } } varList = make(map[string]VarItem) - forums_page := ForumsPage{"Forum List",user,headerVars,forumList,extData} - forums_tmpl, err := c.compile_template("forums.html","templates/","ForumsPage",forums_page,varList) + forums_page := ForumsPage{"Forum List", user, headerVars, forumList} + forums_tmpl, err := c.compileTemplate("forums.html", "templates/", "ForumsPage", forums_page, varList) if err != nil { return err } var topicsList []*TopicsRow - topicsList = append(topicsList,&TopicsRow{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",user3.ID,1,"","127.0.0.1",0,1,"classname","",&user2,"",0,&user3,"General","/forum/general.2"}) - topics_page := TopicsPage{"Topic List",user,headerVars,topicsList,extData} - topics_tmpl, err := c.compile_template("topics.html","templates/","TopicsPage",topics_page,varList) + topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, "Date", "Date", user3.ID, 1, "", "127.0.0.1", 0, 1, "classname", "", &user2, "", 0, &user3, "General", "/forum/general.2"}) + topics_page := TopicsPage{"Topic List", user, headerVars, topicsList} + topics_tmpl, err := c.compileTemplate("topics.html", "templates/", "TopicsPage", topics_page, varList) if err != nil { return err } //var topicList []TopicUser //topicList = append(topicList,TopicUser{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",1,"","127.0.0.1",0,1,"classname","","admin-fred","Admin Fred",config.DefaultGroup,"",0,"","","","",58,false}) - forum_item := Forum{1,"general","General Forum","Where the general stuff happens",true,"all",0,"",0,"","",0,"",0,""} - forum_page := ForumPage{"General Forum",user,headerVars,topicsList,forum_item,1,1,extData} - forum_tmpl, err := c.compile_template("forum.html","templates/","ForumPage",forum_page,varList) + forum_item := Forum{1, "general", "General Forum", "Where the general stuff happens", true, "all", 0, "", 0, "", "", 0, "", 0, ""} + forum_page := ForumPage{"General Forum", user, headerVars, topicsList, forum_item, 1, 1} + forum_tmpl, err := c.compileTemplate("forum.html", "templates/", "ForumPage", forum_page, varList) if err != nil { return err } log.Print("Writing the templates") - go write_template("topic", topic_id_tmpl) - go write_template("topic_alt", topic_id_alt_tmpl) - go write_template("profile", profile_tmpl) - go write_template("forums", forums_tmpl) - go write_template("topics", topics_tmpl) - go write_template("forum", forum_tmpl) + go writeTemplate("topic", topic_id_tmpl) + go writeTemplate("topic_alt", topic_id_alt_tmpl) + go writeTemplate("profile", profile_tmpl) + go writeTemplate("forums", forums_tmpl) + go writeTemplate("topics", topics_tmpl) + go writeTemplate("forum", forum_tmpl) go func() { - err := write_file("./template_list.go","package main\n\n" + c.FragOut) + err := writeFile("./template_list.go", "package main\n\n// nolint\n"+c.FragOut) if err != nil { log.Fatal(err) } @@ -167,66 +167,74 @@ func compile_templates() error { return nil } -func write_template(name string, content string) { - err := write_file("./template_" + name + ".go", content) +func writeTemplate(name string, content string) { + err := writeFile("./template_"+name+".go", content) if err != nil { log.Fatal(err) } } -func init_templates() { +func initTemplates() { if dev.DebugMode { log.Print("Initialising the template system") } - compile_templates() + compileTemplates() // TO-DO: Add support for 64-bit integers // TO-DO: Add support for floats fmap := make(map[string]interface{}) - fmap["add"] = func(left interface{}, right interface{})interface{} { + fmap["add"] = func(left interface{}, right interface{}) interface{} { var left_int int var right_int int switch left := left.(type) { - case uint, uint8, uint16, int, int32: left_int = left.(int) + case uint, uint8, uint16, int, int32: + left_int = left.(int) } switch right := right.(type) { - case uint, uint8, uint16, int, int32: right_int = right.(int) + case uint, uint8, uint16, int, int32: + right_int = right.(int) } return left_int + right_int } - fmap["subtract"] = func(left interface{}, right interface{})interface{} { + fmap["subtract"] = func(left interface{}, right interface{}) interface{} { var left_int int var right_int int switch left := left.(type) { - case uint, uint8, uint16, int, int32: left_int = left.(int) + case uint, uint8, uint16, int, int32: + left_int = left.(int) } switch right := right.(type) { - case uint, uint8, uint16, int, int32: right_int = right.(int) + case uint, uint8, uint16, int, int32: + right_int = right.(int) } return left_int - right_int } - fmap["multiply"] = func(left interface{}, right interface{})interface{} { + fmap["multiply"] = func(left interface{}, right interface{}) interface{} { var left_int int var right_int int switch left := left.(type) { - case uint, uint8, uint16, int, int32: left_int = left.(int) + case uint, uint8, uint16, int, int32: + left_int = left.(int) } switch right := right.(type) { - case uint, uint8, uint16, int, int32: right_int = right.(int) + case uint, uint8, uint16, int, int32: + right_int = right.(int) } return left_int * right_int } - fmap["divide"] = func(left interface{}, right interface{})interface{} { + fmap["divide"] = func(left interface{}, right interface{}) interface{} { var left_int int var right_int int switch left := left.(type) { - case uint, uint8, uint16, int, int32: left_int = left.(int) + case uint, uint8, uint16, int, int32: + left_int = left.(int) } switch right := right.(type) { - case uint, uint8, uint16, int, int32: right_int = right.(int) + case uint, uint8, uint16, int, int32: + right_int = right.(int) } if left_int == 0 || right_int == 0 { return 0 diff --git a/template_list.go b/template_list.go index 40ee1620..0be2e907 100644 --- a/template_list.go +++ b/template_list.go @@ -1,41 +1,44 @@ package main -var header_0 []byte = []byte(` +// nolint +var header_0 = []byte(` `) -var header_1 []byte = []byte(` - - `) -var header_2 []byte = []byte(` +var header_1 = []byte(` +var header_2 = []byte(`/main.css" rel="stylesheet" type="text/css"> `) -var header_4 []byte = []byte(` +var header_3 = []byte(` + + `) +var header_5 = []byte(` `) -var header_5 []byte = []byte(` +var header_6 = []byte(` +var header_7 = []byte(`"> `) -var header_7 []byte = []byte(` +var header_8 = []byte(` +var header_9 = []byte(`"; +var header_10 = []byte(`.supermod_only { display: none !important; }`) +var header_11 = []byte(`
`) -var menu_0 []byte = []byte(`
`) -var footer_1 []byte = []byte(``) -var footer_3 []byte = []byte(` +var footer_1 = []byte(``) +var footer_3 = []byte(`
`) -var topic_alt_0 []byte = []byte(`
`) -var topic_alt_3 []byte = []byte(` +var topic_alt_0 = []byte(`
`) +var topic_alt_3 = []byte(`
`) -var topic_alt_8 []byte = []byte(` +var topic_alt_6 = []byte(`?page=`) +var topic_alt_7 = []byte(`">>`) +var topic_alt_8 = []byte(`
+var topic_alt_9 = []byte(`' method="post">
+var topic_alt_10 = []byte(` topic_sticky_head`) +var topic_alt_11 = []byte(` topic_closed_head`) +var topic_alt_12 = []byte(`">

`) -var topic_alt_13 []byte = []byte(`

+var topic_alt_13 = []byte(` `) -var topic_alt_14 []byte = []byte(`🔒︎`) -var topic_alt_15 []byte = []byte(` +var topic_alt_14 = []byte(`🔒︎`) +var topic_alt_15 = []byte(` +var topic_alt_16 = []byte(`' type="text" /> `) -var topic_alt_17 []byte = []byte(` `) -var topic_alt_18 []byte = []byte(` +var topic_alt_18 = []byte(` `) -var topic_alt_19 []byte = []byte(` +var topic_alt_19 = []byte(`
@@ -295,118 +302,118 @@ var topic_alt_19 []byte = []byte(`
 
+var topic_alt_20 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> 
`) -var topic_alt_22 []byte = []byte(` +var topic_alt_21 = []byte(`" class="the_name">`) +var topic_alt_22 = []byte(` `) -var topic_alt_23 []byte = []byte(`
`) -var topic_alt_25 []byte = []byte(`
`) -var topic_alt_27 []byte = []byte(` +var topic_alt_23 = []byte(`
`) +var topic_alt_25 = []byte(`
`) +var topic_alt_27 = []byte(`
`) -var topic_alt_28 []byte = []byte(`
+var topic_alt_28 = []byte(`
+var topic_alt_29 = []byte(`
`) -var topic_alt_30 []byte = []byte(`+1`) -var topic_alt_32 []byte = []byte(`Edit`) -var topic_alt_34 []byte = []byte(`Delete`) -var topic_alt_36 []byte = []byte(`Unpin`) -var topic_alt_38 []byte = []byte(`Pin`) -var topic_alt_40 []byte = []byte(` +var topic_alt_30 = []byte(`+1`) +var topic_alt_32 = []byte(`Edit`) +var topic_alt_34 = []byte(`Delete`) +var topic_alt_36 = []byte(`Unpin`) +var topic_alt_38 = []byte(`Pin`) +var topic_alt_40 = []byte(` Report +var topic_alt_41 = []byte(`?session=`) +var topic_alt_42 = []byte(`&type=topic" class="action_button report_item">Report `) -var topic_alt_43 []byte = []byte(``) -var topic_alt_44 []byte = []byte(``) -var topic_alt_45 []byte = []byte(` +var topic_alt_43 = []byte(``) +var topic_alt_44 = []byte(``) +var topic_alt_45 = []byte(` `) -var topic_alt_46 []byte = []byte(` +var topic_alt_46 = []byte(` `) -var topic_alt_47 []byte = []byte(``) -var topic_alt_48 []byte = []byte(` up`) -var topic_alt_49 []byte = []byte(` +var topic_alt_47 = []byte(``) +var topic_alt_48 = []byte(` up`) +var topic_alt_49 = []byte(`
`) -var topic_alt_50 []byte = []byte(` +var topic_alt_50 = []byte(`
+var topic_alt_51 = []byte(`action_item`) +var topic_alt_52 = []byte(`">
 
+var topic_alt_53 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> 
`) -var topic_alt_55 []byte = []byte(` +var topic_alt_54 = []byte(`" class="the_name">`) +var topic_alt_55 = []byte(` `) -var topic_alt_56 []byte = []byte(`
`) -var topic_alt_58 []byte = []byte(`
`) -var topic_alt_60 []byte = []byte(` +var topic_alt_56 = []byte(`
`) +var topic_alt_58 = []byte(`
`) +var topic_alt_60 = []byte(`
+var topic_alt_61 = []byte(`style="margin-left: 0px;"`) +var topic_alt_62 = []byte(`> `) -var topic_alt_63 []byte = []byte(` +var topic_alt_63 = []byte(` `) -var topic_alt_64 []byte = []byte(` +var topic_alt_64 = []byte(` `) -var topic_alt_65 []byte = []byte(` +var topic_alt_65 = []byte(` `) -var topic_alt_66 []byte = []byte(` +var topic_alt_66 = []byte(`
`) -var topic_alt_67 []byte = []byte(`
+var topic_alt_67 = []byte(`
`) -var topic_alt_68 []byte = []byte(`+1`) -var topic_alt_70 []byte = []byte(`Edit`) -var topic_alt_72 []byte = []byte(`Delete`) -var topic_alt_74 []byte = []byte(` +var topic_alt_68 = []byte(`+1`) +var topic_alt_70 = []byte(`Edit`) +var topic_alt_72 = []byte(`Delete`) +var topic_alt_74 = []byte(` Report +var topic_alt_75 = []byte(`?session=`) +var topic_alt_76 = []byte(`&type=reply" class="action_button report_item">Report `) -var topic_alt_77 []byte = []byte(``) -var topic_alt_78 []byte = []byte(``) -var topic_alt_79 []byte = []byte(` +var topic_alt_77 = []byte(``) +var topic_alt_78 = []byte(``) +var topic_alt_79 = []byte(` `) -var topic_alt_80 []byte = []byte(` +var topic_alt_80 = []byte(` `) -var topic_alt_81 []byte = []byte(``) -var topic_alt_82 []byte = []byte(` up`) -var topic_alt_83 []byte = []byte(` +var topic_alt_81 = []byte(``) +var topic_alt_82 = []byte(` up`) +var topic_alt_83 = []byte(`
`) -var topic_alt_84 []byte = []byte(` +var topic_alt_84 = []byte(`
`) -var topic_alt_85 []byte = []byte(` +var topic_alt_85 = []byte(` `) -var topic_alt_86 []byte = []byte(` +var topic_alt_86 = []byte(`
+var topic_alt_87 = []byte(`' type="hidden" />
@@ -416,12 +423,12 @@ var topic_alt_87 []byte = []byte(`' type="hidden" />
`) -var topic_alt_88 []byte = []byte(` +var topic_alt_88 = []byte(`
`) -var profile_0 []byte = []byte(` +var profile_0 = []byte(`
`) -var profile_40 []byte = []byte(` +var profile_40 = []byte(`
+var profile_41 = []byte(`' type="hidden" />
@@ -561,11 +568,11 @@ var profile_41 []byte = []byte(`' type="hidden" />
`) -var profile_42 []byte = []byte(` +var profile_42 = []byte(`
`) -var profile_43 []byte = []byte(` +var profile_43 = []byte(` `) -var forums_0 []byte = []byte(` +var forums_0 = []byte(`
@@ -593,44 +600,44 @@ var forums_0 []byte = []byte(`
`) -var forums_1 []byte = []byte(`
+var forums_1 = []byte(`
`) -var forums_4 []byte = []byte(` +var forums_4 = []byte(` `) -var forums_6 []byte = []byte(` +var forums_5 = []byte(`" style="">`) +var forums_6 = []byte(`
`) -var forums_7 []byte = []byte(` +var forums_7 = []byte(`
`) -var forums_8 []byte = []byte(` +var forums_8 = []byte(` `) -var forums_10 []byte = []byte(` +var forums_9 = []byte(`">`) +var forums_10 = []byte(`
No description
`) -var forums_11 []byte = []byte(` +var forums_11 = []byte(` `) -var forums_13 []byte = []byte(` +var forums_12 = []byte(`" style="float: right;font-size: 14px;">`) +var forums_13 = []byte(` `) -var forums_14 []byte = []byte(`
`) -var forums_15 []byte = []byte(``) -var forums_16 []byte = []byte(` +var forums_14 = []byte(`
`) +var forums_15 = []byte(``) +var forums_16 = []byte(`
`) -var forums_17 []byte = []byte(`
You don't have access to any forums.
`) -var forums_18 []byte = []byte(` +var forums_17 = []byte(`
You don't have access to any forums.
`) +var forums_18 = []byte(`
`) -var topics_0 []byte = []byte(` +var topics_0 = []byte(`
@@ -638,133 +645,133 @@ var topics_0 []byte = []byte(`
`) -var topics_1 []byte = []byte(`
+var topics_1 = []byte(`
`) -var topics_8 []byte = []byte(` replies
+var topics_8 = []byte(` replies

`) -var topics_9 []byte = []byte(` +var topics_9 = []byte(` `) -var topics_11 []byte = []byte(` `) -var topics_12 []byte = []byte(``) -var topics_14 []byte = []byte(``) -var topics_15 []byte = []byte(` +var topics_10 = []byte(`">`) +var topics_11 = []byte(` `) +var topics_12 = []byte(``) +var topics_14 = []byte(``) +var topics_15 = []byte(`
Starter: `) -var topics_17 []byte = []byte(` +var topics_16 = []byte(`">Starter: `) +var topics_17 = []byte(` `) -var topics_18 []byte = []byte(` | 🔒︎`) -var topics_19 []byte = []byte(` | 📍︎`) -var topics_20 []byte = []byte(` +var topics_18 = []byte(` | 🔒︎`) +var topics_19 = []byte(` | 📍︎`) +var topics_20 = []byte(`
+var topics_21 = []byte(`background-image: url(`) +var topics_22 = []byte(`);background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;`) +var topics_23 = []byte(`"> `) -var topics_25 []byte = []byte(`
+var topics_24 = []byte(`" class="lastName" style="font-size: 14px;">`) +var topics_25 = []byte(`
Last: `) -var topics_26 []byte = []byte(` +var topics_26 = []byte(`
`) -var topics_27 []byte = []byte(`
There aren't any topics yet.`) -var topics_28 []byte = []byte(` Start one?`) -var topics_29 []byte = []byte(`
`) -var topics_30 []byte = []byte(` +var topics_27 = []byte(`
There aren't any topics yet.`) +var topics_28 = []byte(` Start one?`) +var topics_29 = []byte(`
`) +var topics_30 = []byte(`
`) -var forum_0 []byte = []byte(``) -var forum_3 []byte = []byte(` +var forum_0 = []byte(``) +var forum_3 = []byte(` `) -var forum_8 []byte = []byte(` +var forum_6 = []byte(`?page=`) +var forum_7 = []byte(`">>
`) +var forum_8 = []byte(`

`) -var forum_11 []byte = []byte(`

+var forum_9 = []byte(` has_opt`) +var forum_10 = []byte(`">

`) +var forum_11 = []byte(`

`) -var forum_12 []byte = []byte(` +var forum_12 = []byte(`
+var forum_13 = []byte(`">
`) -var forum_14 []byte = []byte(`
`) -var forum_15 []byte = []byte(` +var forum_14 = []byte(`
`) +var forum_15 = []byte(`
`) -var forum_16 []byte = []byte(` +var forum_16 = []byte(`
`) -var forum_17 []byte = []byte(`
+var forum_17 = []byte(`
`) -var forum_24 []byte = []byte(` replies
+var forum_24 = []byte(` replies

`) -var forum_25 []byte = []byte(` +var forum_25 = []byte(` `) -var forum_27 []byte = []byte(` +var forum_26 = []byte(`">`) +var forum_27 = []byte(`
Starter: `) -var forum_29 []byte = []byte(` +var forum_28 = []byte(`">Starter: `) +var forum_29 = []byte(` `) -var forum_30 []byte = []byte(` | 🔒︎`) -var forum_31 []byte = []byte(` | 📍︎`) -var forum_32 []byte = []byte(` +var forum_30 = []byte(` | 🔒︎`) +var forum_31 = []byte(` | 📍︎`) +var forum_32 = []byte(`
+var forum_33 = []byte(`background-image: url(`) +var forum_34 = []byte(`);background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;`) +var forum_35 = []byte(`"> `) -var forum_37 []byte = []byte(`
+var forum_36 = []byte(`" class="lastName" style="font-size: 14px;">`) +var forum_37 = []byte(`
Last: `) -var forum_38 []byte = []byte(` +var forum_38 = []byte(`
`) -var forum_39 []byte = []byte(`
There aren't any topics in this forum yet.`) -var forum_40 []byte = []byte(` Start one?`) -var forum_42 []byte = []byte(`
`) -var forum_43 []byte = []byte(` +var forum_39 = []byte(`
There aren't any topics in this forum yet.`) +var forum_40 = []byte(` Start one?`) +var forum_42 = []byte(`
`) +var forum_43 = []byte(`
diff --git a/template_profile.go b/template_profile.go index 1b94c59c..1d41b53e 100644 --- a/template_profile.go +++ b/template_profile.go @@ -6,63 +6,68 @@ package main import "net/http" import "strconv" +// nolint func init() { 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 + tmplPtrMap["profile"] = &template_profile_handle + tmplPtrMap["o_profile"] = template_profile } +// nolint func template_profile(tmpl_profile_vars ProfilePage, w http.ResponseWriter) { w.Write(header_0) w.Write([]byte(tmpl_profile_vars.Title)) w.Write(header_1) +w.Write([]byte(tmpl_profile_vars.Header.ThemeName)) +w.Write(header_2) if len(tmpl_profile_vars.Header.Stylesheets) != 0 { for _, item := range tmpl_profile_vars.Header.Stylesheets { -w.Write(header_2) -w.Write([]byte(item)) w.Write(header_3) -} -} +w.Write([]byte(item)) w.Write(header_4) +} +} +w.Write(header_5) if len(tmpl_profile_vars.Header.Scripts) != 0 { for _, item := range tmpl_profile_vars.Header.Scripts { -w.Write(header_5) -w.Write([]byte(item)) w.Write(header_6) -} -} +w.Write([]byte(item)) w.Write(header_7) -w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) +} +} w.Write(header_8) -if !tmpl_profile_vars.CurrentUser.Is_Super_Mod { -w.Write(header_9) -} -w.Write(header_10) -w.Write(menu_0) -w.Write([]byte(tmpl_profile_vars.Header.Site.Name)) -w.Write(menu_1) -if tmpl_profile_vars.CurrentUser.Loggedin { -w.Write(menu_2) -w.Write([]byte(tmpl_profile_vars.CurrentUser.Link)) -w.Write(menu_3) w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) -w.Write(menu_4) -} else { -w.Write(menu_5) +w.Write(header_9) +if !tmpl_profile_vars.CurrentUser.IsSuperMod { +w.Write(header_10) } -w.Write(menu_6) w.Write(header_11) -if tmpl_profile_vars.Header.Widgets.RightSidebar != "" { -w.Write(header_12) +w.Write(menu_0) +w.Write(menu_1) +w.Write([]byte(tmpl_profile_vars.Header.Site.Name)) +w.Write(menu_2) +if tmpl_profile_vars.CurrentUser.Loggedin { +w.Write(menu_3) +w.Write([]byte(tmpl_profile_vars.CurrentUser.Link)) +w.Write(menu_4) +w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) +w.Write(menu_5) +} else { +w.Write(menu_6) } +w.Write(menu_7) +w.Write(header_12) +if tmpl_profile_vars.Header.Widgets.RightSidebar != "" { w.Write(header_13) +} +w.Write(header_14) if len(tmpl_profile_vars.Header.NoticeList) != 0 { for _, item := range tmpl_profile_vars.Header.NoticeList { -w.Write(header_14) -w.Write([]byte(item)) w.Write(header_15) +w.Write([]byte(item)) +w.Write(header_16) } } w.Write(profile_0) @@ -76,9 +81,9 @@ w.Write([]byte(tmpl_profile_vars.ProfileOwner.Tag)) w.Write(profile_4) } w.Write(profile_5) -if tmpl_profile_vars.CurrentUser.Is_Super_Mod && !tmpl_profile_vars.ProfileOwner.Is_Super_Mod { +if tmpl_profile_vars.CurrentUser.IsSuperMod && !tmpl_profile_vars.ProfileOwner.IsSuperMod { w.Write(profile_6) -if tmpl_profile_vars.ProfileOwner.Is_Banned { +if tmpl_profile_vars.ProfileOwner.IsBanned { w.Write(profile_7) w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) w.Write(profile_8) @@ -124,7 +129,7 @@ w.Write([]byte(item.UserLink)) w.Write(profile_28) w.Write([]byte(item.CreatedByName)) w.Write(profile_29) -if tmpl_profile_vars.CurrentUser.Is_Mod { +if tmpl_profile_vars.CurrentUser.IsMod { w.Write(profile_30) w.Write([]byte(strconv.Itoa(item.ID))) w.Write(profile_31) @@ -145,7 +150,7 @@ w.Write(profile_38) } } w.Write(profile_39) -if !tmpl_profile_vars.CurrentUser.Is_Banned { +if !tmpl_profile_vars.CurrentUser.IsBanned { w.Write(profile_40) w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) w.Write(profile_41) diff --git a/template_topic.go b/template_topic.go index 29b363b5..f98c769c 100644 --- a/template_topic.go +++ b/template_topic.go @@ -6,63 +6,68 @@ package main import "net/http" import "strconv" +// nolint func init() { 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 + tmplPtrMap["topic"] = &template_topic_handle + tmplPtrMap["o_topic"] = template_topic } +// nolint func template_topic(tmpl_topic_vars TopicPage, w http.ResponseWriter) { w.Write(header_0) w.Write([]byte(tmpl_topic_vars.Title)) w.Write(header_1) +w.Write([]byte(tmpl_topic_vars.Header.ThemeName)) +w.Write(header_2) if len(tmpl_topic_vars.Header.Stylesheets) != 0 { for _, item := range tmpl_topic_vars.Header.Stylesheets { -w.Write(header_2) -w.Write([]byte(item)) w.Write(header_3) -} -} +w.Write([]byte(item)) w.Write(header_4) +} +} +w.Write(header_5) if len(tmpl_topic_vars.Header.Scripts) != 0 { for _, item := range tmpl_topic_vars.Header.Scripts { -w.Write(header_5) -w.Write([]byte(item)) w.Write(header_6) -} -} +w.Write([]byte(item)) w.Write(header_7) -w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) +} +} w.Write(header_8) -if !tmpl_topic_vars.CurrentUser.Is_Super_Mod { -w.Write(header_9) -} -w.Write(header_10) -w.Write(menu_0) -w.Write([]byte(tmpl_topic_vars.Header.Site.Name)) -w.Write(menu_1) -if tmpl_topic_vars.CurrentUser.Loggedin { -w.Write(menu_2) -w.Write([]byte(tmpl_topic_vars.CurrentUser.Link)) -w.Write(menu_3) w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) -w.Write(menu_4) -} else { -w.Write(menu_5) +w.Write(header_9) +if !tmpl_topic_vars.CurrentUser.IsSuperMod { +w.Write(header_10) } -w.Write(menu_6) w.Write(header_11) -if tmpl_topic_vars.Header.Widgets.RightSidebar != "" { -w.Write(header_12) +w.Write(menu_0) +w.Write(menu_1) +w.Write([]byte(tmpl_topic_vars.Header.Site.Name)) +w.Write(menu_2) +if tmpl_topic_vars.CurrentUser.Loggedin { +w.Write(menu_3) +w.Write([]byte(tmpl_topic_vars.CurrentUser.Link)) +w.Write(menu_4) +w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) +w.Write(menu_5) +} else { +w.Write(menu_6) } +w.Write(menu_7) +w.Write(header_12) +if tmpl_topic_vars.Header.Widgets.RightSidebar != "" { w.Write(header_13) +} +w.Write(header_14) if len(tmpl_topic_vars.Header.NoticeList) != 0 { for _, item := range tmpl_topic_vars.Header.NoticeList { -w.Write(header_14) -w.Write([]byte(item)) w.Write(header_15) +w.Write([]byte(item)) +w.Write(header_16) } } w.Write(topic_0) @@ -90,14 +95,14 @@ w.Write(topic_10) if tmpl_topic_vars.Topic.Sticky { w.Write(topic_11) } else { -if tmpl_topic_vars.Topic.Is_Closed { +if tmpl_topic_vars.Topic.IsClosed { w.Write(topic_12) } } w.Write(topic_13) w.Write([]byte(tmpl_topic_vars.Topic.Title)) w.Write(topic_14) -if tmpl_topic_vars.Topic.Is_Closed { +if tmpl_topic_vars.Topic.IsClosed { w.Write(topic_15) } if tmpl_topic_vars.CurrentUser.Perms.EditTopic { @@ -160,103 +165,113 @@ w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) w.Write(topic_42) } } +if tmpl_topic_vars.CurrentUser.Perms.ViewIPs { w.Write(topic_43) -w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) +w.Write([]byte(tmpl_topic_vars.Topic.IPAddress)) w.Write(topic_44) -w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) +} w.Write(topic_45) -if tmpl_topic_vars.Topic.LikeCount > 0 { +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) w.Write(topic_46) -w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.LikeCount))) +w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) w.Write(topic_47) +if tmpl_topic_vars.Topic.LikeCount > 0 { +w.Write(topic_48) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.LikeCount))) +w.Write(topic_49) } if tmpl_topic_vars.Topic.Tag != "" { -w.Write(topic_48) -w.Write([]byte(tmpl_topic_vars.Topic.Tag)) -w.Write(topic_49) -} else { w.Write(topic_50) -w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level))) +w.Write([]byte(tmpl_topic_vars.Topic.Tag)) w.Write(topic_51) -} +} else { w.Write(topic_52) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level))) +w.Write(topic_53) +} +w.Write(topic_54) if len(tmpl_topic_vars.ItemList) != 0 { for _, item := range tmpl_topic_vars.ItemList { if item.ActionType != "" { -w.Write(topic_53) -w.Write([]byte(item.ActionIcon)) -w.Write(topic_54) -w.Write([]byte(item.ActionType)) w.Write(topic_55) -} else { +w.Write([]byte(item.ActionIcon)) w.Write(topic_56) -w.Write([]byte(item.ClassName)) +w.Write([]byte(item.ActionType)) w.Write(topic_57) -if item.Avatar != "" { +} else { w.Write(topic_58) -w.Write([]byte(item.Avatar)) +w.Write([]byte(item.ClassName)) w.Write(topic_59) -if item.ContentLines <= 5 { +if item.Avatar != "" { w.Write(topic_60) -} +w.Write([]byte(item.Avatar)) w.Write(topic_61) -} +if item.ContentLines <= 5 { w.Write(topic_62) -w.Write([]byte(item.ContentHtml)) +} w.Write(topic_63) -w.Write([]byte(item.UserLink)) +} w.Write(topic_64) -w.Write([]byte(item.CreatedByName)) +w.Write([]byte(item.ContentHtml)) w.Write(topic_65) -if tmpl_topic_vars.CurrentUser.Perms.LikeItem { +w.Write([]byte(item.UserLink)) w.Write(topic_66) -w.Write([]byte(strconv.Itoa(item.ID))) +w.Write([]byte(item.CreatedByName)) w.Write(topic_67) -if item.Liked { +if tmpl_topic_vars.CurrentUser.Perms.LikeItem { w.Write(topic_68) -} -w.Write(topic_69) -} -if tmpl_topic_vars.CurrentUser.Perms.EditReply { -w.Write(topic_70) w.Write([]byte(strconv.Itoa(item.ID))) +w.Write(topic_69) +if item.Liked { +w.Write(topic_70) +} w.Write(topic_71) } -if tmpl_topic_vars.CurrentUser.Perms.DeleteReply { +if tmpl_topic_vars.CurrentUser.Perms.EditReply { w.Write(topic_72) w.Write([]byte(strconv.Itoa(item.ID))) w.Write(topic_73) } +if tmpl_topic_vars.CurrentUser.Perms.DeleteReply { w.Write(topic_74) w.Write([]byte(strconv.Itoa(item.ID))) w.Write(topic_75) -w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) -w.Write(topic_76) -if item.LikeCount > 0 { -w.Write(topic_77) -w.Write([]byte(strconv.Itoa(item.LikeCount))) -w.Write(topic_78) } -if item.Tag != "" { +if tmpl_topic_vars.CurrentUser.Perms.ViewIPs { +w.Write(topic_76) +w.Write([]byte(item.IPAddress)) +w.Write(topic_77) +} +w.Write(topic_78) +w.Write([]byte(strconv.Itoa(item.ID))) w.Write(topic_79) -w.Write([]byte(item.Tag)) +w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) w.Write(topic_80) -} else { +if item.LikeCount > 0 { w.Write(topic_81) -w.Write([]byte(strconv.Itoa(item.Level))) +w.Write([]byte(strconv.Itoa(item.LikeCount))) w.Write(topic_82) } +if item.Tag != "" { w.Write(topic_83) -} -} -} +w.Write([]byte(item.Tag)) w.Write(topic_84) -if tmpl_topic_vars.CurrentUser.Perms.CreateReply { +} else { w.Write(topic_85) -w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) +w.Write([]byte(strconv.Itoa(item.Level))) w.Write(topic_86) } w.Write(topic_87) +} +} +} +w.Write(topic_88) +if tmpl_topic_vars.CurrentUser.Perms.CreateReply { +w.Write(topic_89) +w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) +w.Write(topic_90) +} +w.Write(topic_91) w.Write(footer_0) if tmpl_topic_vars.Header.Widgets.RightSidebar != "" { w.Write(footer_1) diff --git a/template_topic_alt.go b/template_topic_alt.go index ced58eaf..a2f2a86a 100644 --- a/template_topic_alt.go +++ b/template_topic_alt.go @@ -6,63 +6,68 @@ package main import "net/http" import "strconv" +// nolint func init() { 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 + tmplPtrMap["topic_alt"] = &template_topic_alt_handle + tmplPtrMap["o_topic_alt"] = template_topic_alt } +// nolint func template_topic_alt(tmpl_topic_alt_vars TopicPage, w http.ResponseWriter) { w.Write(header_0) w.Write([]byte(tmpl_topic_alt_vars.Title)) w.Write(header_1) +w.Write([]byte(tmpl_topic_alt_vars.Header.ThemeName)) +w.Write(header_2) if len(tmpl_topic_alt_vars.Header.Stylesheets) != 0 { for _, item := range tmpl_topic_alt_vars.Header.Stylesheets { -w.Write(header_2) -w.Write([]byte(item)) w.Write(header_3) -} -} +w.Write([]byte(item)) w.Write(header_4) +} +} +w.Write(header_5) if len(tmpl_topic_alt_vars.Header.Scripts) != 0 { for _, item := range tmpl_topic_alt_vars.Header.Scripts { -w.Write(header_5) -w.Write([]byte(item)) w.Write(header_6) -} -} +w.Write([]byte(item)) w.Write(header_7) -w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) +} +} w.Write(header_8) -if !tmpl_topic_alt_vars.CurrentUser.Is_Super_Mod { -w.Write(header_9) -} -w.Write(header_10) -w.Write(menu_0) -w.Write([]byte(tmpl_topic_alt_vars.Header.Site.Name)) -w.Write(menu_1) -if tmpl_topic_alt_vars.CurrentUser.Loggedin { -w.Write(menu_2) -w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link)) -w.Write(menu_3) w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) -w.Write(menu_4) -} else { -w.Write(menu_5) +w.Write(header_9) +if !tmpl_topic_alt_vars.CurrentUser.IsSuperMod { +w.Write(header_10) } -w.Write(menu_6) w.Write(header_11) -if tmpl_topic_alt_vars.Header.Widgets.RightSidebar != "" { -w.Write(header_12) +w.Write(menu_0) +w.Write(menu_1) +w.Write([]byte(tmpl_topic_alt_vars.Header.Site.Name)) +w.Write(menu_2) +if tmpl_topic_alt_vars.CurrentUser.Loggedin { +w.Write(menu_3) +w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link)) +w.Write(menu_4) +w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) +w.Write(menu_5) +} else { +w.Write(menu_6) } +w.Write(menu_7) +w.Write(header_12) +if tmpl_topic_alt_vars.Header.Widgets.RightSidebar != "" { w.Write(header_13) +} +w.Write(header_14) if len(tmpl_topic_alt_vars.Header.NoticeList) != 0 { for _, item := range tmpl_topic_alt_vars.Header.NoticeList { -w.Write(header_14) -w.Write([]byte(item)) w.Write(header_15) +w.Write([]byte(item)) +w.Write(header_16) } } if tmpl_topic_alt_vars.Page > 1 { @@ -89,14 +94,14 @@ w.Write(topic_alt_9) if tmpl_topic_alt_vars.Topic.Sticky { w.Write(topic_alt_10) } else { -if tmpl_topic_alt_vars.Topic.Is_Closed { +if tmpl_topic_alt_vars.Topic.IsClosed { w.Write(topic_alt_11) } } w.Write(topic_alt_12) w.Write([]byte(tmpl_topic_alt_vars.Topic.Title)) w.Write(topic_alt_13) -if tmpl_topic_alt_vars.Topic.Is_Closed { +if tmpl_topic_alt_vars.Topic.IsClosed { w.Write(topic_alt_14) } if tmpl_topic_alt_vars.CurrentUser.Perms.EditTopic { @@ -163,7 +168,7 @@ w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) w.Write(topic_alt_42) if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs { w.Write(topic_alt_43) -w.Write([]byte(tmpl_topic_alt_vars.Topic.IpAddress)) +w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress)) w.Write(topic_alt_44) } } @@ -236,7 +241,7 @@ w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) w.Write(topic_alt_76) if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs { w.Write(topic_alt_77) -w.Write([]byte(item.IpAddress)) +w.Write([]byte(item.IPAddress)) w.Write(topic_alt_78) } } diff --git a/template_topics.go b/template_topics.go index fb929819..3bf2fe00 100644 --- a/template_topics.go +++ b/template_topics.go @@ -3,66 +3,71 @@ // Code generated by Gosora. More below: /* 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 "net/http" import "strconv" +import "net/http" +// nolint func init() { template_topics_handle = template_topics //o_template_topics_handle = template_topics ctemplates = append(ctemplates,"topics") - tmpl_ptr_map["topics"] = &template_topics_handle - tmpl_ptr_map["o_topics"] = template_topics + tmplPtrMap["topics"] = &template_topics_handle + tmplPtrMap["o_topics"] = template_topics } +// nolint func template_topics(tmpl_topics_vars TopicsPage, w http.ResponseWriter) { w.Write(header_0) w.Write([]byte(tmpl_topics_vars.Title)) w.Write(header_1) +w.Write([]byte(tmpl_topics_vars.Header.ThemeName)) +w.Write(header_2) if len(tmpl_topics_vars.Header.Stylesheets) != 0 { for _, item := range tmpl_topics_vars.Header.Stylesheets { -w.Write(header_2) -w.Write([]byte(item)) w.Write(header_3) -} -} +w.Write([]byte(item)) w.Write(header_4) +} +} +w.Write(header_5) if len(tmpl_topics_vars.Header.Scripts) != 0 { for _, item := range tmpl_topics_vars.Header.Scripts { -w.Write(header_5) -w.Write([]byte(item)) w.Write(header_6) -} -} +w.Write([]byte(item)) w.Write(header_7) -w.Write([]byte(tmpl_topics_vars.CurrentUser.Session)) +} +} w.Write(header_8) -if !tmpl_topics_vars.CurrentUser.Is_Super_Mod { -w.Write(header_9) -} -w.Write(header_10) -w.Write(menu_0) -w.Write([]byte(tmpl_topics_vars.Header.Site.Name)) -w.Write(menu_1) -if tmpl_topics_vars.CurrentUser.Loggedin { -w.Write(menu_2) -w.Write([]byte(tmpl_topics_vars.CurrentUser.Link)) -w.Write(menu_3) w.Write([]byte(tmpl_topics_vars.CurrentUser.Session)) -w.Write(menu_4) -} else { -w.Write(menu_5) +w.Write(header_9) +if !tmpl_topics_vars.CurrentUser.IsSuperMod { +w.Write(header_10) } -w.Write(menu_6) w.Write(header_11) -if tmpl_topics_vars.Header.Widgets.RightSidebar != "" { -w.Write(header_12) +w.Write(menu_0) +w.Write(menu_1) +w.Write([]byte(tmpl_topics_vars.Header.Site.Name)) +w.Write(menu_2) +if tmpl_topics_vars.CurrentUser.Loggedin { +w.Write(menu_3) +w.Write([]byte(tmpl_topics_vars.CurrentUser.Link)) +w.Write(menu_4) +w.Write([]byte(tmpl_topics_vars.CurrentUser.Session)) +w.Write(menu_5) +} else { +w.Write(menu_6) } +w.Write(menu_7) +w.Write(header_12) +if tmpl_topics_vars.Header.Widgets.RightSidebar != "" { w.Write(header_13) +} +w.Write(header_14) if len(tmpl_topics_vars.Header.NoticeList) != 0 { for _, item := range tmpl_topics_vars.Header.NoticeList { -w.Write(header_14) -w.Write([]byte(item)) w.Write(header_15) +w.Write([]byte(item)) +w.Write(header_16) } } w.Write(topics_0) @@ -72,7 +77,7 @@ w.Write(topics_1) if item.Sticky { w.Write(topics_2) } else { -if item.Is_Closed { +if item.IsClosed { w.Write(topics_3) } } @@ -103,7 +108,7 @@ w.Write([]byte(item.Creator.Link)) w.Write(topics_16) w.Write([]byte(item.Creator.Name)) w.Write(topics_17) -if item.Is_Closed { +if item.IsClosed { w.Write(topics_18) } if item.Sticky { diff --git a/templates.go b/templates.go index 729190ba..b9cd549b 100644 --- a/templates.go +++ b/templates.go @@ -1,64 +1,56 @@ package main import ( - "log" - "fmt" "bytes" - "strings" + "fmt" + "log" "strconv" + "strings" //"regexp" - "reflect" - "path/filepath" "io/ioutil" + "path/filepath" + "reflect" "text/template/parse" ) // TO-DO: Turn this file into a library var ctemplates []string -var tmpl_ptr_map map[string]interface{} = make(map[string]interface{}) -var text_overlap_list map[string]int +var tmplPtrMap = make(map[string]interface{}) +var textOverlapList = make(map[string]int) -func init() { - text_overlap_list = make(map[string]int) -} - -type VarItem struct -{ - Name string +// nolint +type VarItem struct { + Name string Destination string - Type string + Type string } - -type VarItemReflect struct -{ - Name string +type VarItemReflect struct { + Name string Destination string - Value reflect.Value + Value reflect.Value } - -type CTemplateSet struct -{ - tlist map[string]*parse.Tree - dir string - funcMap map[string]interface{} - importMap map[string]string - Fragments map[string]int +type CTemplateSet struct { + tlist map[string]*parse.Tree + dir string + funcMap map[string]interface{} + importMap map[string]string + Fragments map[string]int FragmentCursor map[string]int - FragOut string - varList map[string]VarItem - localVars map[string]map[string]VarItemReflect - stats map[string]int - pVarList string - pVarPosition int - previousNode parse.NodeType - currentNode parse.NodeType - nextNode parse.NodeType + FragOut string + varList map[string]VarItem + localVars map[string]map[string]VarItemReflect + stats map[string]int + pVarList string + pVarPosition int + previousNode parse.NodeType + currentNode parse.NodeType + nextNode parse.NodeType //tempVars map[string]string - doImports bool + doImports bool expectsInt interface{} } -func (c *CTemplateSet) compile_template(name string, dir string, expects string, expectsInt interface{}, varList map[string]VarItem) (out string, err error) { +func (c *CTemplateSet) compileTemplate(name string, dir string, expects string, expectsInt interface{}, varList map[string]VarItem) (out string, err error) { if dev.DebugMode { fmt.Println("Compiling template '" + name + "'") } @@ -66,23 +58,23 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string, c.dir = dir c.doImports = true c.funcMap = map[string]interface{}{ - "and": "&&", - "not": "!", - "or": "||", - "eq": true, - "ge": true, - "gt": true, - "le": true, - "lt": true, - "ne": true, - "add": true, + "and": "&&", + "not": "!", + "or": "||", + "eq": true, + "ge": true, + "gt": true, + "le": true, + "lt": true, + "ne": true, + "add": true, "subtract": true, "multiply": true, - "divide": true, + "divide": true, } c.importMap = map[string]string{ - "net/http":"net/http", + "net/http": "net/http", } c.varList = varList //c.pVarList = "" @@ -102,8 +94,8 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string, } tree := parse.New(name, c.funcMap) - var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree) - tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap) + var treeSet = make(map[string]*parse.Tree) + tree, err = tree.Parse(content, "{{", "}}", treeSet, c.funcMap) if err != nil { return "", err } @@ -122,7 +114,7 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string, } c.localVars = make(map[string]map[string]VarItemReflect) c.localVars[fname] = make(map[string]VarItemReflect) - c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect} + c.localVars[fname]["."] = VarItemReflect{".", varholder, holdreflect} if c.Fragments == nil { c.Fragments = make(map[string]int) } @@ -143,9 +135,9 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string, c.previousNode = c.currentNode c.currentNode = node.Type() if treeLength != (index + 1) { - c.nextNode = subtree.Root.Nodes[index + 1].Type() + c.nextNode = subtree.Root.Nodes[index+1].Type() } - out += c.compile_switch(varholder, holdreflect, fname, node) + out += c.compileSwitch(varholder, holdreflect, fname, node) } var importList string @@ -162,12 +154,12 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string, fout := "// +build !no_templategen\n\n// Code generated by Gosora. More below:\n/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */\n" fout += "package main\n" + importList + c.pVarList + "\n" - fout += "func init() {\n\ttemplate_" + fname +"_handle = template_" + fname + "\n\t//o_template_" + fname +"_handle = template_" + fname + "\n\tctemplates = append(ctemplates,\"" + fname + "\")\n\ttmpl_ptr_map[\"" + fname + "\"] = &template_" + fname + "_handle\n\ttmpl_ptr_map[\"o_" + fname + "\"] = template_" + fname + "\n}\n\n" - fout += "func template_" + fname + "(tmpl_" + fname + "_vars " + expects + ", w http.ResponseWriter) {\n" + varString + out + "}\n" + fout += "// nolint\nfunc init() {\n\ttemplate_" + fname + "_handle = template_" + fname + "\n\t//o_template_" + fname + "_handle = template_" + fname + "\n\tctemplates = append(ctemplates,\"" + fname + "\")\n\ttmplPtrMap[\"" + fname + "\"] = &template_" + fname + "_handle\n\ttmplPtrMap[\"o_" + fname + "\"] = template_" + fname + "\n}\n\n" + fout += "// nolint\nfunc template_" + fname + "(tmpl_" + fname + "_vars " + expects + ", w http.ResponseWriter) {\n" + varString + out + "}\n" - fout = strings.Replace(fout,`)) -w.Write([]byte(`," + ",-1) - fout = strings.Replace(fout,"` + `","",-1) + fout = strings.Replace(fout, `)) +w.Write([]byte(`, " + ", -1) + fout = strings.Replace(fout, "` + `", "", -1) //spstr := "`([:space:]*)`" //whitespace_writes := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`) //fout = whitespace_writes.ReplaceAllString(fout,"") @@ -186,315 +178,314 @@ w.Write([]byte(`," + ",-1) return fout, nil } -func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) { +func (c *CTemplateSet) compileSwitch(varholder string, holdreflect reflect.Value, templateName string, node interface{}) (out string) { if dev.SuperDebug { - fmt.Println("in compile_switch") + fmt.Println("in compileSwitch") } switch node := node.(type) { - case *parse.ActionNode: + case *parse.ActionNode: + if dev.SuperDebug { + fmt.Println("Action Node") + } + if node.Pipe == nil { + break + } + for _, cmd := range node.Pipe.Cmds { + out += c.compileSubswitch(varholder, holdreflect, templateName, cmd) + } + return out + case *parse.IfNode: + if dev.SuperDebug { + fmt.Println("If Node:") + fmt.Println("node.Pipe", node.Pipe) + } + + var expr string + for _, cmd := range node.Pipe.Cmds { if dev.SuperDebug { - fmt.Println("Action Node") + fmt.Println("If Node Bit:", cmd) + fmt.Println("If Node Bit Type:", reflect.ValueOf(cmd).Type().Name()) } - if node.Pipe == nil { - break - } - for _, cmd := range node.Pipe.Cmds { - out += c.compile_subswitch(varholder, holdreflect, template_name, cmd) - } - return out - case *parse.IfNode: + expr += c.compileVarswitch(varholder, holdreflect, templateName, cmd) if dev.SuperDebug { - fmt.Println("If Node:") - fmt.Println("node.Pipe",node.Pipe) + fmt.Println("If Node Expression Step:", c.compileVarswitch(varholder, holdreflect, templateName, cmd)) } + } - var expr string - for _, cmd := range node.Pipe.Cmds { - if dev.SuperDebug { - fmt.Println("If Node Bit:",cmd) - fmt.Println("If Node Bit Type:",reflect.ValueOf(cmd).Type().Name()) - } - expr += c.compile_varswitch(varholder, holdreflect, template_name, cmd) - if dev.SuperDebug { - fmt.Println("If Node Expression Step:",c.compile_varswitch(varholder, holdreflect, template_name, cmd)) - } - } + if dev.SuperDebug { + fmt.Println("If Node Expression:", expr) + } + c.previousNode = c.currentNode + c.currentNode = parse.NodeList + c.nextNode = -1 + if node.ElseList == nil { if dev.SuperDebug { - fmt.Println("If Node Expression:",expr) + fmt.Println("Selected Branch 1") } + return "if " + expr + " {\n" + c.compileSwitch(varholder, holdreflect, templateName, node.List) + "}\n" + } - c.previousNode = c.currentNode - c.currentNode = parse.NodeList - c.nextNode = -1 - if node.ElseList == nil { - if dev.SuperDebug { - fmt.Println("Selected Branch 1") - } - return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "}\n" - } else { - if dev.SuperDebug { - fmt.Println("Selected Branch 2") - } - return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "} else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n" - } - case *parse.ListNode: + if dev.SuperDebug { + fmt.Println("Selected Branch 2") + } + return "if " + expr + " {\n" + c.compileSwitch(varholder, holdreflect, templateName, node.List) + "} else {\n" + c.compileSwitch(varholder, holdreflect, templateName, node.ElseList) + "}\n" + case *parse.ListNode: + if dev.SuperDebug { + fmt.Println("List Node") + } + for _, subnode := range node.Nodes { + out += c.compileSwitch(varholder, holdreflect, templateName, subnode) + } + return out + case *parse.RangeNode: + if dev.SuperDebug { + fmt.Println("Range Node!") + fmt.Println(node.Pipe) + } + + var outVal reflect.Value + for _, cmd := range node.Pipe.Cmds { if dev.SuperDebug { - fmt.Println("List Node") - } - for _, subnode := range node.Nodes { - out += c.compile_switch(varholder, holdreflect, template_name, subnode) - } - return out - case *parse.RangeNode: - if dev.SuperDebug { - fmt.Println("Range Node!") - fmt.Println(node.Pipe) + fmt.Println("Range Bit:", cmd) } + out, outVal = c.compileReflectswitch(varholder, holdreflect, templateName, cmd) + } - var outVal reflect.Value - for _, cmd := range node.Pipe.Cmds { - if dev.SuperDebug { - fmt.Println("Range Bit:", cmd) - } - out, outVal = c.compile_reflectswitch(varholder, holdreflect, template_name, cmd) - } + if dev.SuperDebug { + fmt.Println("Returned:", out) + fmt.Println("Range Kind Switch!") + } - if dev.SuperDebug { - fmt.Println("Returned:", out) - fmt.Println("Range Kind Switch!") - } - - switch outVal.Kind() { - case reflect.Map: - var item reflect.Value - for _, key := range outVal.MapKeys() { - item = outVal.MapIndex(key) - } - - if node.ElseList != nil { - out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n} else {\n" + c.compile_switch("item", item, template_name, node.ElseList) + "}\n" - } else { - out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}" - } - case reflect.Slice: - if outVal.Len() == 0 { - panic("The sample data needs at-least one or more elements for the slices. We're looking into removing this requirement at some point!") - } - 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 "" + switch outVal.Kind() { + case reflect.Map: + var item reflect.Value + for _, key := range outVal.MapKeys() { + item = outVal.MapIndex(key) } if node.ElseList != nil { - out += " else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n" + out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compileSwitch("item", item, templateName, node.List) + "}\n} else {\n" + c.compileSwitch("item", item, templateName, node.ElseList) + "}\n" } else { - out += "\n" + out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compileSwitch("item", item, templateName, node.List) + "}\n}" } - return out - case *parse.TemplateNode: - return c.compile_subtemplate(varholder, holdreflect, node) - case *parse.TextNode: - c.previousNode = c.currentNode - c.currentNode = node.Type() - c.nextNode = 0 - tmpText := bytes.TrimSpace(node.Text) - if len(tmpText) == 0 { - return "" - } else { - //return "w.Write([]byte(`" + string(node.Text) + "`))\n" - fragment_name := template_name + "_" + strconv.Itoa(c.FragmentCursor[template_name]) - _, ok := c.Fragments[fragment_name] - if !ok { - c.Fragments[fragment_name] = len(node.Text) - c.FragOut += "var " + fragment_name + " []byte = []byte(`" + string(node.Text) + "`)\n" - } - c.FragmentCursor[template_name] = c.FragmentCursor[template_name] + 1 - return "w.Write(" + fragment_name + ")\n" + case reflect.Slice: + if outVal.Len() == 0 { + panic("The sample data needs at-least one or more elements for the slices. We're looking into removing this requirement at some point!") } - default: - panic("Unknown Node in main switch") + item := outVal.Index(0) + out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compileSwitch("item", item, templateName, node.List) + "}\n}" + case reflect.Invalid: + return "" + } + + if node.ElseList != nil { + out += " else {\n" + c.compileSwitch(varholder, holdreflect, templateName, node.ElseList) + "}\n" + } else { + out += "\n" + } + return out + case *parse.TemplateNode: + return c.compileSubtemplate(varholder, holdreflect, node) + case *parse.TextNode: + c.previousNode = c.currentNode + c.currentNode = node.Type() + c.nextNode = 0 + tmpText := bytes.TrimSpace(node.Text) + if len(tmpText) == 0 { + return "" + } + + //return "w.Write([]byte(`" + string(node.Text) + "`))\n" + fragmentName := templateName + "_" + strconv.Itoa(c.FragmentCursor[templateName]) + _, ok := c.Fragments[fragmentName] + if !ok { + c.Fragments[fragmentName] = len(node.Text) + c.FragOut += "var " + fragmentName + " = []byte(`" + string(node.Text) + "`)\n" + } + c.FragmentCursor[templateName] = c.FragmentCursor[templateName] + 1 + return "w.Write(" + fragmentName + ")\n" + default: + panic("Unknown Node in main switch") } return "" } -func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { +func (c *CTemplateSet) compileSubswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string) { if dev.SuperDebug { - fmt.Println("in compile_subswitch") + fmt.Println("in compileSubswitch") } firstWord := node.Args[0] switch n := firstWord.(type) { - case *parse.FieldNode: + case *parse.FieldNode: + if dev.SuperDebug { + fmt.Println("Field Node:", n.Ident) + } + + /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Variable declarations are coming soon! */ + cur := holdreflect + + var varbit string + if cur.Kind() == reflect.Interface { + cur = cur.Elem() + varbit += ".(" + cur.Type().Name() + ")" + } + + for _, id := range n.Ident { if dev.SuperDebug { - fmt.Println("Field Node:",n.Ident) + fmt.Println("Data Kind:", cur.Kind().String()) + fmt.Println("Field Bit:", id) } - /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Variable declarations are coming soon! */ - cur := holdreflect + if cur.Kind() == reflect.Ptr { + if dev.SuperDebug { + fmt.Println("Looping over pointer") + } + for cur.Kind() == reflect.Ptr { + cur = cur.Elem() + } - var varbit string - if cur.Kind() == reflect.Interface { - cur = cur.Elem() - varbit += ".(" + cur.Type().Name() + ")" - } - - for _, id := range n.Ident { if dev.SuperDebug { fmt.Println("Data Kind:", cur.Kind().String()) fmt.Println("Field Bit:", id) } + } - if cur.Kind() == reflect.Ptr { - if dev.SuperDebug { - fmt.Println("Looping over pointer") - } - for cur.Kind() == reflect.Ptr { - cur = cur.Elem() - } + if !cur.IsValid() { + panic(varholder + varbit + "^\n" + "Invalid value. Maybe, it doesn't exist?") + } - if dev.SuperDebug { - fmt.Println("Data Kind:", cur.Kind().String()) - fmt.Println("Field Bit:", id) - } - } - - if !cur.IsValid() { - panic(varholder + varbit + "^\n" + "Invalid value. Maybe, it doesn't exist?") - } - - cur = cur.FieldByName(id) - if cur.Kind() == reflect.Interface { - cur = cur.Elem() - // TO-DO: Surely, there's a better way of detecting this? - /*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" && cur.Type().PkgPath() != "" { - c.importMap["html/template"] = "html/template" - varbit += "." + id + ".(" + strings.TrimPrefix(cur.Type().PkgPath(),"html/") + "." + cur.Type().Name() + ")" - } else { - varbit += "." + id + ".(" + cur.Type().Name() + ")" - } + cur = cur.FieldByName(id) + if cur.Kind() == reflect.Interface { + cur = cur.Elem() + // TO-DO: Surely, there's a better way of detecting this? + /*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" && cur.Type().PkgPath() != "" { + c.importMap["html/template"] = "html/template" + varbit += "." + id + ".(" + strings.TrimPrefix(cur.Type().PkgPath(), "html/") + "." + cur.Type().Name() + ")" } else { - varbit += "." + id - } - if dev.SuperDebug { - fmt.Println("End Cycle") + varbit += "." + id + ".(" + cur.Type().Name() + ")" } + } else { + varbit += "." + id } - out = c.compile_varsub(varholder + varbit, cur) + if dev.SuperDebug { + fmt.Println("End Cycle") + } + } + out = c.compileVarsub(varholder+varbit, cur) - for _, varItem := range c.varList { - if strings.HasPrefix(out, varItem.Destination) { - out = strings.Replace(out, varItem.Destination, varItem.Name, 1) - } + for _, varItem := range c.varList { + if strings.HasPrefix(out, varItem.Destination) { + out = strings.Replace(out, varItem.Destination, varItem.Name, 1) } - return out - case *parse.DotNode: - if dev.SuperDebug { - fmt.Println("Dot Node:",node.String()) - } - return c.compile_varsub(varholder, holdreflect) - case *parse.NilNode: - panic("Nil is not a command x.x") - case *parse.VariableNode: - if dev.SuperDebug { - fmt.Println("Variable Node:", n.String()) - fmt.Println(n.Ident) - } - varname, reflectVal := c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) - return c.compile_varsub(varname, reflectVal) - case *parse.StringNode: - return n.Quoted - case *parse.IdentifierNode: - if dev.SuperDebug { - fmt.Println("Identifier Node:", node) - fmt.Println("Identifier Node Args:", node.Args) - } - return c.compile_varsub(c.compile_identswitch(varholder, holdreflect, template_name, node)) - default: - fmt.Println("Unknown Kind:", reflect.ValueOf(firstWord).Elem().Kind()) - fmt.Println("Unknown Type:", reflect.ValueOf(firstWord).Elem().Type().Name()) - panic("I don't know what node this is") + } + return out + case *parse.DotNode: + if dev.SuperDebug { + fmt.Println("Dot Node:", node.String()) + } + return c.compileVarsub(varholder, holdreflect) + case *parse.NilNode: + panic("Nil is not a command x.x") + case *parse.VariableNode: + if dev.SuperDebug { + fmt.Println("Variable Node:", n.String()) + fmt.Println(n.Ident) + } + varname, reflectVal := c.compileIfVarsub(n.String(), varholder, templateName, holdreflect) + return c.compileVarsub(varname, reflectVal) + case *parse.StringNode: + return n.Quoted + case *parse.IdentifierNode: + if dev.SuperDebug { + fmt.Println("Identifier Node:", node) + fmt.Println("Identifier Node Args:", node.Args) + } + return c.compileVarsub(c.compileIdentswitch(varholder, holdreflect, templateName, node)) + default: + fmt.Println("Unknown Kind:", reflect.ValueOf(firstWord).Elem().Kind()) + fmt.Println("Unknown Type:", reflect.ValueOf(firstWord).Elem().Type().Name()) + panic("I don't know what node this is") } - return "" } -func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { +func (c *CTemplateSet) compileVarswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string) { if dev.SuperDebug { fmt.Println("in compile_varswitch") } firstWord := node.Args[0] switch n := firstWord.(type) { - case *parse.FieldNode: - if dev.SuperDebug { - fmt.Println("Field Node:", n.Ident) - for _, id := range n.Ident { - fmt.Println("Field Bit:", id) - } + case *parse.FieldNode: + if dev.SuperDebug { + fmt.Println("Field Node:", n.Ident) + for _, id := range n.Ident { + fmt.Println("Field Bit:", id) } + } - /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ - return c.compile_boolsub(n.String(), varholder, template_name, holdreflect) - case *parse.ChainNode: - if dev.SuperDebug { - fmt.Println("Chain Node:", n.Node) - fmt.Println("Chain Node Args:", node.Args) - } - break - case *parse.IdentifierNode: - if dev.SuperDebug { - fmt.Println("Identifier Node:", node) - fmt.Println("Identifier Node Args:", node.Args) - } - return c.compile_identswitch_n(varholder, holdreflect, template_name, node) - case *parse.DotNode: - return varholder - case *parse.VariableNode: - if dev.SuperDebug { - fmt.Println("Variable Node:", n.String()) - fmt.Println("Variable Node Identifier:", n.Ident) - } - out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) - return out - case *parse.NilNode: - panic("Nil is not a command x.x") - case *parse.PipeNode: - if dev.SuperDebug { - fmt.Println("Pipe Node!") - fmt.Println(n) - fmt.Println("Args:", node.Args) - } - out += c.compile_identswitch_n(varholder, holdreflect, template_name, node) + /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ + return c.compileBoolsub(n.String(), varholder, templateName, holdreflect) + case *parse.ChainNode: + if dev.SuperDebug { + fmt.Println("Chain Node:", n.Node) + fmt.Println("Chain Node Args:", node.Args) + } + break + case *parse.IdentifierNode: + if dev.SuperDebug { + fmt.Println("Identifier Node:", node) + fmt.Println("Identifier Node Args:", node.Args) + } + return c.compileIdentswitchN(varholder, holdreflect, templateName, node) + case *parse.DotNode: + return varholder + case *parse.VariableNode: + if dev.SuperDebug { + fmt.Println("Variable Node:", n.String()) + fmt.Println("Variable Node Identifier:", n.Ident) + } + out, _ = c.compileIfVarsub(n.String(), varholder, templateName, holdreflect) + return out + case *parse.NilNode: + panic("Nil is not a command x.x") + case *parse.PipeNode: + if dev.SuperDebug { + fmt.Println("Pipe Node!") + fmt.Println(n) + fmt.Println("Args:", node.Args) + } + out += c.compileIdentswitchN(varholder, holdreflect, templateName, node) - if dev.SuperDebug { - fmt.Println("Out:", out) - } - return out - default: - fmt.Println("Unknown Kind:", reflect.ValueOf(firstWord).Elem().Kind()) - fmt.Println("Unknown Type:", reflect.ValueOf(firstWord).Elem().Type().Name()) - panic("I don't know what node this is! Grr...") + if dev.SuperDebug { + fmt.Println("Out:", out) + } + return out + default: + fmt.Println("Unknown Kind:", reflect.ValueOf(firstWord).Elem().Kind()) + fmt.Println("Unknown Type:", reflect.ValueOf(firstWord).Elem().Type().Name()) + panic("I don't know what node this is! Grr...") } return "" } -func (c *CTemplateSet) compile_identswitch_n(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { +func (c *CTemplateSet) compileIdentswitchN(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string) { if dev.SuperDebug { fmt.Println("in compile_identswitch_n") } - out, _ = c.compile_identswitch(varholder, holdreflect, template_name, node) + out, _ = c.compileIdentswitch(varholder, holdreflect, templateName, node) return out } -func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, val reflect.Value) { +func (c *CTemplateSet) compileIdentswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string, val reflect.Value) { if dev.SuperDebug { - fmt.Println("in compile_identswitch") + fmt.Println("in compileIdentswitch") } //var outbuf map[int]string - ArgLoop: +ArgLoop: for pos := 0; pos < len(node.Args); pos++ { id := node.Args[pos] if dev.SuperDebug { @@ -502,219 +493,215 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect fmt.Println("ID:", id) } switch id.String() { - case "not": - out += "!" - case "or": - if dev.SuperDebug { - fmt.Println("Building or function") - } - if pos == 0 { - fmt.Println("pos:", pos) - panic("or is missing a left operand") - return out, val - } - if len(node.Args) <= pos { - fmt.Println("post pos:", pos) - fmt.Println("len(node.Args):", len(node.Args)) - panic("or is missing a right operand") - return out, val - } + case "not": + out += "!" + case "or": + if dev.SuperDebug { + fmt.Println("Building or function") + } + if pos == 0 { + fmt.Println("pos:", pos) + panic("or is missing a left operand") + } + if len(node.Args) <= pos { + fmt.Println("post pos:", pos) + fmt.Println("len(node.Args):", len(node.Args)) + panic("or is missing a right operand") + } - left := c.compile_boolsub(node.Args[pos - 1].String(), varholder, template_name, holdreflect) - _, funcExists := c.funcMap[node.Args[pos + 1].String()] + left := c.compileBoolsub(node.Args[pos-1].String(), varholder, templateName, holdreflect) + _, funcExists := c.funcMap[node.Args[pos+1].String()] - var right string - if !funcExists { - right = c.compile_boolsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect) - } + var right string + if !funcExists { + right = c.compileBoolsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) + } - out += left + " || " + right + out += left + " || " + right - if dev.SuperDebug { - fmt.Println("Left operand:", node.Args[pos - 1]) - fmt.Println("Right operand:", node.Args[pos + 1]) - } + if dev.SuperDebug { + fmt.Println("Left operand:", node.Args[pos-1]) + fmt.Println("Right operand:", node.Args[pos+1]) + } - if !funcExists { - pos++ - } + if !funcExists { + pos++ + } - if dev.SuperDebug { - fmt.Println("pos:", pos) - fmt.Println("len(node.Args):", len(node.Args)) - } - case "and": - if dev.SuperDebug { - fmt.Println("Building and function") - } - if pos == 0 { - fmt.Println("pos:", pos) - panic("and is missing a left operand") - return out, val - } - if len(node.Args) <= pos { - fmt.Println("post pos:", pos) - fmt.Println("len(node.Args):", len(node.Args)) - panic("and is missing a right operand") - return out, val - } + if dev.SuperDebug { + fmt.Println("pos:", pos) + fmt.Println("len(node.Args):", len(node.Args)) + } + case "and": + if dev.SuperDebug { + fmt.Println("Building and function") + } + if pos == 0 { + fmt.Println("pos:", pos) + panic("and is missing a left operand") + } + if len(node.Args) <= pos { + fmt.Println("post pos:", pos) + fmt.Println("len(node.Args):", len(node.Args)) + panic("and is missing a right operand") + } - left := c.compile_boolsub(node.Args[pos - 1].String(), varholder, template_name, holdreflect) - _, funcExists := c.funcMap[node.Args[pos + 1].String()] + left := c.compileBoolsub(node.Args[pos-1].String(), varholder, templateName, holdreflect) + _, funcExists := c.funcMap[node.Args[pos+1].String()] - var right string - if !funcExists { - right = c.compile_boolsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect) - } + var right string + if !funcExists { + right = c.compileBoolsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) + } - out += left + " && " + right + out += left + " && " + right - if dev.SuperDebug { - fmt.Println("Left operand:", node.Args[pos - 1]) - fmt.Println("Right operand:", node.Args[pos + 1]) - } + if dev.SuperDebug { + fmt.Println("Left operand:", node.Args[pos-1]) + fmt.Println("Right operand:", node.Args[pos+1]) + } - if !funcExists { - pos++ - } + if !funcExists { + pos++ + } - if dev.SuperDebug { - fmt.Println("pos:", pos) - fmt.Println("len(node.Args):", len(node.Args)) - } - case "le": - out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) - if dev.SuperDebug { - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "lt": - out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " < " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) - if dev.SuperDebug { - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "gt": - out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " > " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) - if dev.SuperDebug { - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "ge": - out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " >= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) - if dev.SuperDebug { - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "eq": - out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " == " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) - if dev.SuperDebug { - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "ne": - out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " != " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) - if dev.SuperDebug { - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "add": - param1, val2 := c.compile_if_varsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect) - param2, val3 := c.compile_if_varsub(node.Args[pos + 2].String(), varholder, template_name, holdreflect) + if dev.SuperDebug { + fmt.Println("pos:", pos) + fmt.Println("len(node.Args):", len(node.Args)) + } + case "le": + out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " <= " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) + if dev.SuperDebug { + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "lt": + out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " < " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) + if dev.SuperDebug { + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "gt": + out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " > " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) + if dev.SuperDebug { + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "ge": + out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " >= " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) + if dev.SuperDebug { + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "eq": + out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " == " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) + if dev.SuperDebug { + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "ne": + out += c.compileIfVarsubN(node.Args[pos+1].String(), varholder, templateName, holdreflect) + " != " + c.compileIfVarsubN(node.Args[pos+2].String(), varholder, templateName, holdreflect) + if dev.SuperDebug { + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "add": + param1, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) + param2, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect) - if val2.IsValid() { - val = val2 - } else if val3.IsValid() { - val = val3 - } else { - numSample := 1 - val = reflect.ValueOf(numSample) - } + if val2.IsValid() { + val = val2 + } else if val3.IsValid() { + val = val3 + } else { + numSample := 1 + val = reflect.ValueOf(numSample) + } - out += param1 + " + " + param2 - if dev.SuperDebug { - fmt.Println("add") - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "subtract": - param1, val2 := c.compile_if_varsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect) - param2, val3 := c.compile_if_varsub(node.Args[pos + 2].String(), varholder, template_name, holdreflect) + out += param1 + " + " + param2 + if dev.SuperDebug { + fmt.Println("add") + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "subtract": + param1, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) + param2, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect) - if val2.IsValid() { - val = val2 - } else if val3.IsValid() { - val = val3 - } else { - numSample := 1 - val = reflect.ValueOf(numSample) - } + if val2.IsValid() { + val = val2 + } else if val3.IsValid() { + val = val3 + } else { + numSample := 1 + val = reflect.ValueOf(numSample) + } - out += param1 + " - " + param2 - if dev.SuperDebug { - fmt.Println("subtract") - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "divide": - param1, val2 := c.compile_if_varsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect) - param2, val3 := c.compile_if_varsub(node.Args[pos + 2].String(), varholder, template_name, holdreflect) + out += param1 + " - " + param2 + if dev.SuperDebug { + fmt.Println("subtract") + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "divide": + param1, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) + param2, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect) - if val2.IsValid() { - val = val2 - } else if val3.IsValid() { - val = val3 - } else { - numSample := 1 - val = reflect.ValueOf(numSample) - } + if val2.IsValid() { + val = val2 + } else if val3.IsValid() { + val = val3 + } else { + numSample := 1 + val = reflect.ValueOf(numSample) + } - out += param1 + " / " + param2 - if dev.SuperDebug { - fmt.Println("divide") - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) - } - break ArgLoop - case "multiply": - param1, val2 := c.compile_if_varsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect) - param2, val3 := c.compile_if_varsub(node.Args[pos + 2].String(), varholder, template_name, holdreflect) + out += param1 + " / " + param2 + if dev.SuperDebug { + fmt.Println("divide") + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + case "multiply": + param1, val2 := c.compileIfVarsub(node.Args[pos+1].String(), varholder, templateName, holdreflect) + param2, val3 := c.compileIfVarsub(node.Args[pos+2].String(), varholder, templateName, holdreflect) - if val2.IsValid() { - val = val2 - } else if val3.IsValid() { - val = val3 - } else { - numSample := 1 - val = reflect.ValueOf(numSample) - } + if val2.IsValid() { + val = val2 + } else if val3.IsValid() { + val = val3 + } else { + numSample := 1 + val = reflect.ValueOf(numSample) + } - out += param1 + " * " + param2 - if dev.SuperDebug { - fmt.Println("multiply") - fmt.Println("node.Args[pos + 1]", node.Args[pos + 1]) - fmt.Println("node.Args[pos + 2]", node.Args[pos + 2]) + out += param1 + " * " + param2 + if dev.SuperDebug { + fmt.Println("multiply") + fmt.Println("node.Args[pos + 1]", node.Args[pos+1]) + fmt.Println("node.Args[pos + 2]", node.Args[pos+2]) + } + break ArgLoop + default: + if dev.SuperDebug { + fmt.Println("Variable!") + } + if len(node.Args) > (pos + 1) { + nextNode := node.Args[pos+1].String() + if nextNode == "or" || nextNode == "and" { + continue } - break ArgLoop - default: - if dev.SuperDebug { - fmt.Println("Variable!") - } - if len(node.Args) > (pos + 1) { - next_node := node.Args[pos + 1].String() - if next_node == "or" || next_node == "and" { - continue - } - } - out += c.compile_if_varsub_n(id.String(), varholder, template_name, holdreflect) + } + out += c.compileIfVarsubN(id.String(), varholder, templateName, holdreflect) } } @@ -724,60 +711,60 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect return out, val } -func (c *CTemplateSet) compile_reflectswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, outVal reflect.Value) { +func (c *CTemplateSet) compileReflectswitch(varholder string, holdreflect reflect.Value, templateName string, node *parse.CommandNode) (out string, outVal reflect.Value) { if dev.SuperDebug { - fmt.Println("in compile_reflectswitch") + fmt.Println("in compileReflectswitch") } firstWord := node.Args[0] switch n := firstWord.(type) { - case *parse.FieldNode: - if dev.SuperDebug { - fmt.Println("Field Node:", n.Ident) - for _, id := range n.Ident { - fmt.Println("Field Bit:", id) - } + case *parse.FieldNode: + if dev.SuperDebug { + fmt.Println("Field Node:", n.Ident) + for _, id := range n.Ident { + fmt.Println("Field Bit:", id) } - /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ - return c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) - case *parse.ChainNode: - if dev.SuperDebug { - fmt.Println("Chain Node:", n.Node) - fmt.Println("node.Args", node.Args) - } - return "", outVal - case *parse.DotNode: - return varholder, holdreflect - case *parse.NilNode: - panic("Nil is not a command x.x") - default: - //panic("I don't know what node this is") + } + /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ + return c.compileIfVarsub(n.String(), varholder, templateName, holdreflect) + case *parse.ChainNode: + if dev.SuperDebug { + fmt.Println("Chain Node:", n.Node) + fmt.Println("node.Args", node.Args) + } + return "", outVal + case *parse.DotNode: + return varholder, holdreflect + case *parse.NilNode: + panic("Nil is not a command x.x") + default: + //panic("I don't know what node this is") } return "", outVal } -func (c *CTemplateSet) compile_if_varsub_n(varname string, varholder string, template_name string, cur reflect.Value) (out string) { +func (c *CTemplateSet) compileIfVarsubN(varname string, varholder string, templateName string, cur reflect.Value) (out string) { if dev.SuperDebug { - fmt.Println("in compile_if_varsub_n") + fmt.Println("in compileIfVarsubN") } - out, _ = c.compile_if_varsub(varname, varholder, template_name, cur) + out, _ = c.compileIfVarsub(varname, varholder, templateName, cur) return out } -func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, template_name string, cur reflect.Value) (out string, val reflect.Value) { +func (c *CTemplateSet) compileIfVarsub(varname string, varholder string, templateName string, cur reflect.Value) (out string, val reflect.Value) { if dev.SuperDebug { - fmt.Println("in compile_if_varsub") + fmt.Println("in compileIfVarsub") } if varname[0] != '.' && varname[0] != '$' { return varname, cur } - bits := strings.Split(varname,".") + bits := strings.Split(varname, ".") if varname[0] == '$' { var res VarItemReflect if varname[1] == '.' { - res = c.localVars[template_name]["."] + res = c.localVars[templateName]["."] } else { - res = c.localVars[template_name][strings.TrimPrefix(bits[0],"$")] + res = c.localVars[templateName][strings.TrimPrefix(bits[0], "$")] } out += res.Destination cur = res.Value @@ -793,7 +780,7 @@ func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, templ out += varholder } } - bits[0] = strings.TrimPrefix(bits[0],"$") + bits[0] = strings.TrimPrefix(bits[0], "$") if dev.SuperDebug { fmt.Println("Cur Kind:", cur.Kind()) @@ -869,28 +856,31 @@ func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, templ return out, cur } -func (c *CTemplateSet) compile_boolsub(varname string, varholder string, template_name string, val reflect.Value) string { +func (c *CTemplateSet) compileBoolsub(varname string, varholder string, templateName string, val reflect.Value) string { if dev.SuperDebug { - fmt.Println("in compile_boolsub") + fmt.Println("in compileBoolsub") } - out, val := c.compile_if_varsub(varname, varholder, template_name, val) + out, val := c.compileIfVarsub(varname, varholder, templateName, val) switch val.Kind() { - case reflect.Int: out += " > 0" - case reflect.Bool: // Do nothing - case reflect.String: out += " != \"\"" - case reflect.Int64: out += " > 0" - default: - fmt.Println("Variable Name:", varname) - fmt.Println("Variable Holder:", varholder) - fmt.Println("Variable Kind:", val.Kind()) - panic("I don't know what this variable's type is o.o\n") + case reflect.Int: + out += " > 0" + case reflect.Bool: // Do nothing + case reflect.String: + out += " != \"\"" + case reflect.Int64: + out += " > 0" + default: + fmt.Println("Variable Name:", varname) + fmt.Println("Variable Holder:", varholder) + fmt.Println("Variable Kind:", val.Kind()) + panic("I don't know what this variable's type is o.o\n") } return out } -func (c *CTemplateSet) compile_varsub(varname string, val reflect.Value) string { +func (c *CTemplateSet) compileVarsub(varname string, val reflect.Value) string { if dev.SuperDebug { - fmt.Println("in compile_varsub") + fmt.Println("in compileVarsub") } for _, varItem := range c.varList { if strings.HasPrefix(varname, varItem.Destination) { @@ -910,34 +900,33 @@ func (c *CTemplateSet) compile_varsub(varname string, val reflect.Value) string } switch val.Kind() { - case reflect.Int: - c.importMap["strconv"] = "strconv" - return "w.Write([]byte(strconv.Itoa(" + varname + ")))\n" - case reflect.Bool: - return "if " + varname + " {\nw.Write([]byte(\"true\"))} else {\nw.Write([]byte(\"false\"))\n}\n" - case reflect.String: - if val.Type().Name() != "string" && !strings.HasPrefix(varname,"string(") { - return "w.Write([]byte(string(" + varname + ")))\n" - } else { - return "w.Write([]byte(" + varname + "))\n" - } - case reflect.Int64: - c.importMap["strconv"] = "strconv" - return "w.Write([]byte(strconv.FormatInt(" + varname + ", 10)))" - default: - if !val.IsValid() { - panic(varname + "^\n" + "Invalid value. Maybe, it doesn't exist?") - } - fmt.Println("Unknown Variable Name:", varname) - fmt.Println("Unknown Kind:", val.Kind()) - fmt.Println("Unknown Type:", val.Type().Name()) - panic("// I don't know what this variable's type is o.o\n") + case reflect.Int: + c.importMap["strconv"] = "strconv" + return "w.Write([]byte(strconv.Itoa(" + varname + ")))\n" + case reflect.Bool: + return "if " + varname + " {\nw.Write([]byte(\"true\"))} else {\nw.Write([]byte(\"false\"))\n}\n" + case reflect.String: + if val.Type().Name() != "string" && !strings.HasPrefix(varname, "string(") { + return "w.Write([]byte(string(" + varname + ")))\n" + } + return "w.Write([]byte(" + varname + "))\n" + case reflect.Int64: + c.importMap["strconv"] = "strconv" + return "w.Write([]byte(strconv.FormatInt(" + varname + ", 10)))" + default: + if !val.IsValid() { + panic(varname + "^\n" + "Invalid value. Maybe, it doesn't exist?") + } + fmt.Println("Unknown Variable Name:", varname) + fmt.Println("Unknown Kind:", val.Kind()) + fmt.Println("Unknown Type:", val.Type().Name()) + panic("// I don't know what this variable's type is o.o\n") } } -func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect reflect.Value, node *parse.TemplateNode) (out string) { +func (c *CTemplateSet) compileSubtemplate(pvarholder string, pholdreflect reflect.Value, node *parse.TemplateNode) (out string) { if dev.SuperDebug { - fmt.Println("in compile_subtemplate") + fmt.Println("in compileSubtemplate") fmt.Println("Template Node:", node.Name) } @@ -948,15 +937,15 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle for _, cmd := range node.Pipe.Cmds { firstWord := cmd.Args[0] switch firstWord.(type) { - case *parse.DotNode: - varholder = pvarholder - holdreflect = pholdreflect - break - case *parse.NilNode: - panic("Nil is not a command x.x") - default: - out = "var " + varholder + " := false\n" - out += c.compile_command(cmd) + case *parse.DotNode: + varholder = pvarholder + holdreflect = pholdreflect + break + case *parse.NilNode: + panic("Nil is not a command x.x") + default: + out = "var " + varholder + " := false\n" + out += c.compileCommand(cmd) } } } @@ -973,8 +962,8 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle } tree := parse.New(node.Name, c.funcMap) - var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree) - tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap) + var treeSet = make(map[string]*parse.Tree) + tree, err = tree.Parse(content, "{{", "}}", treeSet, c.funcMap) if err != nil { log.Fatal(err) } @@ -986,7 +975,7 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle } c.localVars[fname] = make(map[string]VarItemReflect) - c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect} + c.localVars[fname]["."] = VarItemReflect{".", varholder, holdreflect} c.FragmentCursor[fname] = 0 treeLength := len(subtree.Root.Nodes) @@ -998,32 +987,31 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle c.previousNode = c.currentNode c.currentNode = node.Type() if treeLength != (index + 1) { - c.nextNode = subtree.Root.Nodes[index + 1].Type() + c.nextNode = subtree.Root.Nodes[index+1].Type() } - out += c.compile_switch(varholder, holdreflect, fname, node) + out += c.compileSwitch(varholder, holdreflect, fname, node) } return out } -func (c *CTemplateSet) compile_command(*parse.CommandNode) (out string) { +func (c *CTemplateSet) compileCommand(*parse.CommandNode) (out string) { panic("Uh oh! Something went wrong!") - return "" } // TO-DO: Write unit tests for this func minify(data string) string { - data = strings.Replace(data,"\t","",-1) - data = strings.Replace(data,"\v","",-1) - data = strings.Replace(data,"\n","",-1) - data = strings.Replace(data,"\r","",-1) - data = strings.Replace(data," "," ",-1) + data = strings.Replace(data, "\t", "", -1) + data = strings.Replace(data, "\v", "", -1) + data = strings.Replace(data, "\n", "", -1) + data = strings.Replace(data, "\r", "", -1) + data = strings.Replace(data, " ", " ", -1) return data } // TO-DO: Strip comments // TO-DO: Handle CSS nested in +
{{template "menu.html" .}}
diff --git a/templates/ip-search.html b/templates/ip-search.html new file mode 100644 index 00000000..7c76174f --- /dev/null +++ b/templates/ip-search.html @@ -0,0 +1,18 @@ +{{template "header.html" . }} +
+ + +
+
Searching for {{.IP}}
+
+
+ {{range .ItemList}}
+ {{.Name}} +
+ {{else}}
No users found.
{{end}} +
+ +
+{{template "footer.html" . }} diff --git a/templates/menu.html b/templates/menu.html index daf27f36..9b16549a 100644 --- a/templates/menu.html +++ b/templates/menu.html @@ -1,7 +1,7 @@