2016-12-02 07:38:54 +00:00
package main
import (
"net/http"
"database/sql"
_ "github.com/go-sql-driver/mysql"
"log"
2016-12-05 07:21:17 +00:00
"mime"
2016-12-08 14:11:18 +00:00
"strings"
"strconv"
2016-12-02 07:38:54 +00:00
"path/filepath"
2016-12-08 14:11:18 +00:00
"os"
2016-12-05 07:21:17 +00:00
"io/ioutil"
2016-12-02 07:38:54 +00:00
"html/template"
)
const hour int = 60 * 60
const day int = hour * 24
const month int = day * 30
const year int = day * 365
2016-12-02 15:03:31 +00:00
const kilobyte int = 1024
const megabyte int = 1024 * 1024
2016-12-02 07:38:54 +00:00
const saltLength int = 32
const sessionLength int = 80
2016-12-04 06:16:59 +00:00
2016-12-02 07:38:54 +00:00
var db * sql . DB
var get_session_stmt * sql . Stmt
var create_topic_stmt * sql . Stmt
var create_reply_stmt * sql . Stmt
2016-12-03 13:45:08 +00:00
var update_forum_cache_stmt * sql . Stmt
2016-12-02 07:38:54 +00:00
var edit_topic_stmt * sql . Stmt
var edit_reply_stmt * sql . Stmt
var delete_reply_stmt * sql . Stmt
2016-12-03 10:25:39 +00:00
var delete_topic_stmt * sql . Stmt
var stick_topic_stmt * sql . Stmt
var unstick_topic_stmt * sql . Stmt
2016-12-02 07:38:54 +00:00
var login_stmt * sql . Stmt
var update_session_stmt * sql . Stmt
var logout_stmt * sql . Stmt
var set_password_stmt * sql . Stmt
2016-12-02 11:00:07 +00:00
var get_password_stmt * sql . Stmt
2016-12-02 15:03:31 +00:00
var set_avatar_stmt * sql . Stmt
2016-12-03 08:09:40 +00:00
var set_username_stmt * sql . Stmt
2016-12-02 07:38:54 +00:00
var register_stmt * sql . Stmt
var username_exists_stmt * sql . Stmt
2016-12-08 14:11:18 +00:00
var change_group_stmt * sql . Stmt
2016-12-07 09:34:09 +00:00
var create_profile_reply_stmt * sql . Stmt
var edit_profile_reply_stmt * sql . Stmt
var delete_profile_reply_stmt * sql . Stmt
2016-12-04 06:16:59 +00:00
2016-12-04 10:44:28 +00:00
var create_forum_stmt * sql . Stmt
2016-12-06 10:26:48 +00:00
var delete_forum_stmt * sql . Stmt
var update_forum_stmt * sql . Stmt
2016-12-04 10:44:28 +00:00
2016-12-02 07:38:54 +00:00
var templates = template . Must ( template . ParseGlob ( "templates/*" ) )
2016-12-08 14:11:18 +00:00
var custom_pages = template . Must ( template . ParseGlob ( "pages/*" ) )
2016-12-04 06:16:59 +00:00
var no_css_tmpl = template . CSS ( "" )
var staff_css_tmpl = template . CSS ( staff_css )
var groups map [ int ] Group = make ( map [ int ] Group )
2016-12-06 10:26:48 +00:00
var forums map [ int ] Forum = make ( map [ int ] Forum )
2016-12-05 07:21:17 +00:00
var static_files map [ string ] SFile = make ( map [ string ] SFile )
2016-12-02 07:38:54 +00:00
func init_database ( err error ) {
2016-12-02 08:07:56 +00:00
if ( dbpassword != "" ) {
dbpassword = ":" + dbpassword
2016-12-02 07:38:54 +00:00
}
2016-12-08 14:11:18 +00:00
db , err = sql . Open ( "mysql" , dbuser + dbpassword + "@tcp(" + dbhost + ":" + dbport + ")/" + dbname + "?collation=utf8mb4_general_ci" )
2016-12-02 07:38:54 +00:00
if err != nil {
log . Fatal ( err )
}
// Make sure that the connection is alive..
err = db . Ping ( )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing get_session statement." )
2016-12-02 15:03:31 +00:00
get_session_stmt , err = db . Prepare ( "SELECT `uid`, `name`, `group`, `is_super_admin`, `session`, `avatar` FROM `users` WHERE `uid` = ? AND `session` = ? AND `session` <> ''" )
2016-12-02 07:38:54 +00:00
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing create_topic statement." )
2016-12-03 04:50:35 +00:00
create_topic_stmt , err = db . Prepare ( "INSERT INTO topics(title,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)" )
2016-12-02 07:38:54 +00:00
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing create_reply statement." )
2016-12-03 04:50:35 +00:00
create_reply_stmt , err = db . Prepare ( "INSERT INTO replies(tid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)" )
2016-12-02 07:38:54 +00:00
if err != nil {
log . Fatal ( err )
}
2016-12-03 13:45:08 +00:00
log . Print ( "Preparing update_forum_cache statement." )
update_forum_cache_stmt , err = db . Prepare ( "UPDATE forums SET lastTopic = ?, lastTopicID = ?, lastReplyer = ?, lastReplyerID = ?, lastTopicTime = NOW() WHERE fid = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-02 07:38:54 +00:00
log . Print ( "Preparing edit_topic statement." )
2016-12-03 04:50:35 +00:00
edit_topic_stmt , err = db . Prepare ( "UPDATE topics SET title = ?, content = ?, parsed_content = ?, is_closed = ? WHERE tid = ?" )
2016-12-02 07:38:54 +00:00
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing edit_reply statement." )
2016-12-03 04:50:35 +00:00
edit_reply_stmt , err = db . Prepare ( "UPDATE replies SET content = ?, parsed_content = ? WHERE rid = ?" )
2016-12-02 07:38:54 +00:00
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing delete_reply statement." )
delete_reply_stmt , err = db . Prepare ( "DELETE FROM replies WHERE rid = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-03 10:25:39 +00:00
log . Print ( "Preparing delete_topic statement." )
delete_topic_stmt , err = db . Prepare ( "DELETE FROM topics WHERE tid = ?" )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing stick_topic statement." )
stick_topic_stmt , err = db . Prepare ( "UPDATE topics SET sticky = 1 WHERE tid = ?" )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing unstick_topic statement." )
unstick_topic_stmt , err = db . Prepare ( "UPDATE topics SET sticky = 0 WHERE tid = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-02 07:38:54 +00:00
log . Print ( "Preparing login statement." )
login_stmt , err = db . Prepare ( "SELECT `uid`, `name`, `password`, `salt` FROM `users` WHERE `name` = ?" )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing update_session statement." )
update_session_stmt , err = db . Prepare ( "UPDATE users SET session = ? WHERE uid = ?" )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing logout statement." )
logout_stmt , err = db . Prepare ( "UPDATE users SET session = '' WHERE uid = ?" )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing set_password statement." )
set_password_stmt , err = db . Prepare ( "UPDATE users SET password = ?, salt = ? WHERE uid = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-02 11:00:07 +00:00
log . Print ( "Preparing get_password statement." )
get_password_stmt , err = db . Prepare ( "SELECT `password`, `salt` FROM `users` WHERE `uid` = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-02 15:03:31 +00:00
log . Print ( "Preparing set_avatar statement." )
set_avatar_stmt , err = db . Prepare ( "UPDATE users SET avatar = ? WHERE uid = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-03 08:09:40 +00:00
log . Print ( "Preparing set_username statement." )
set_username_stmt , err = db . Prepare ( "UPDATE users SET name = ? WHERE uid = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-02 07:38:54 +00:00
// Add an admin version of register_stmt with more flexibility
// create_account_stmt, err = db.Prepare("INSERT INTO
log . Print ( "Preparing register statement." )
2016-12-08 14:11:18 +00:00
register_stmt , err = db . Prepare ( "INSERT INTO users(`name`,`password`,`salt`,`group`,`is_super_admin`,`session`) VALUES(?,?,?," + strconv . Itoa ( default_group ) + ",0,?)" )
2016-12-02 07:38:54 +00:00
if err != nil {
log . Fatal ( err )
}
2016-12-02 15:03:31 +00:00
log . Print ( "Preparing username_exists statement." )
2016-12-02 07:38:54 +00:00
username_exists_stmt , err = db . Prepare ( "SELECT `name` FROM `users` WHERE `name` = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-04 06:16:59 +00:00
2016-12-08 14:11:18 +00:00
log . Print ( "Preparing change_group statement." )
change_group_stmt , err = db . Prepare ( "UPDATE `users` SET `group` = ? WHERE `uid` = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-07 09:34:09 +00:00
log . Print ( "Preparing create_profile_reply statement." )
create_profile_reply_stmt , err = db . Prepare ( "INSERT INTO users_replies(uid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)" )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing edit_profile_reply statement." )
edit_profile_reply_stmt , err = db . Prepare ( "UPDATE users_replies SET content = ?, parsed_content = ? WHERE rid = ?" )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing delete_profile_reply statement." )
delete_profile_reply_stmt , err = db . Prepare ( "DELETE FROM users_replies WHERE rid = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-04 10:44:28 +00:00
log . Print ( "Preparing create_forum statement." )
create_forum_stmt , err = db . Prepare ( "INSERT INTO forums(name) VALUES(?)" )
if err != nil {
log . Fatal ( err )
}
2016-12-06 10:26:48 +00:00
log . Print ( "Preparing delete_forum statement." )
delete_forum_stmt , err = db . Prepare ( "DELETE FROM forums WHERE fid = ?" )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Preparing update_forum statement." )
update_forum_stmt , err = db . Prepare ( "UPDATE forums SET name = ? WHERE fid = ?" )
if err != nil {
log . Fatal ( err )
}
2016-12-04 06:16:59 +00:00
log . Print ( "Loading the usergroups." )
2016-12-07 13:46:14 +00:00
rows , err := db . Query ( "SELECT gid,name,permissions,is_mod,is_admin,is_banned,tag FROM users_groups" )
2016-12-04 06:16:59 +00:00
if err != nil {
log . Fatal ( err )
}
defer rows . Close ( )
for rows . Next ( ) {
2016-12-07 13:46:14 +00:00
group := Group { 0 , "" , "" , false , false , false , "" }
err := rows . Scan ( & group . ID , & group . Name , & group . Permissions , & group . Is_Mod , & group . Is_Admin , & group . Is_Banned , & group . Tag )
2016-12-04 06:16:59 +00:00
if err != nil {
log . Fatal ( err )
}
groups [ group . ID ] = group
}
err = rows . Err ( )
if err != nil {
log . Fatal ( err )
}
2016-12-06 10:26:48 +00:00
log . Print ( "Loading the forums." )
2016-12-07 09:34:09 +00:00
rows , err = db . Query ( "SELECT fid, name, active, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime FROM forums" )
2016-12-06 10:26:48 +00:00
if err != nil {
log . Fatal ( err )
}
defer rows . Close ( )
for rows . Next ( ) {
forum := Forum { 0 , "" , true , "" , 0 , "" , 0 , "" }
2016-12-07 09:34:09 +00:00
err := rows . Scan ( & forum . ID , & forum . Name , & forum . Active , & forum . LastTopic , & forum . LastTopicID , & forum . LastReplyer , & forum . LastReplyerID , & forum . LastTopicTime )
2016-12-06 10:26:48 +00:00
if err != nil {
log . Fatal ( err )
}
if forum . LastTopicID != 0 {
forum . LastTopicTime , err = relative_time ( forum . LastTopicTime )
if err != nil {
log . Fatal ( err )
}
} else {
forum . LastTopic = "None"
forum . LastTopicTime = ""
}
forums [ forum . ID ] = forum
}
err = rows . Err ( )
if err != nil {
log . Fatal ( err )
}
log . Print ( "Adding the uncategorised forum" )
forums [ 0 ] = Forum { 0 , "Uncategorised" , uncategorised_forum_visible , "" , 0 , "" , 0 , "" }
log . Print ( "Adding the reports forum" )
forums [ - 1 ] = Forum { - 1 , "Reports" , false , "" , 0 , "" , 0 , "" }
2016-12-02 07:38:54 +00:00
}
func main ( ) {
var err error
init_database ( err ) ;
2016-12-05 07:21:17 +00:00
log . Print ( "Loading the static files." )
2016-12-08 14:11:18 +00:00
err = filepath . Walk ( "./public" , func ( path string , f os . FileInfo , err error ) error {
2016-12-05 07:21:17 +00:00
if f . IsDir ( ) {
2016-12-08 14:11:18 +00:00
return nil
2016-12-05 07:21:17 +00:00
}
2016-12-08 14:11:18 +00:00
path = strings . Replace ( path , "\\" , "/" , - 1 )
data , err := ioutil . ReadFile ( path )
2016-12-05 07:21:17 +00:00
if err != nil {
2016-12-08 14:11:18 +00:00
return err
2016-12-05 07:21:17 +00:00
}
2016-12-08 14:11:18 +00:00
path = strings . TrimPrefix ( path , "public/" )
log . Print ( "Added the '" + path + "' static file." )
static_files [ "/static/" + path ] = SFile { data , 0 , int64 ( len ( data ) ) , mime . TypeByExtension ( filepath . Ext ( "/public/" + path ) ) , f , f . ModTime ( ) . UTC ( ) . Format ( http . TimeFormat ) }
return nil
} )
if err != nil {
log . Fatal ( err )
2016-12-05 07:21:17 +00:00
}
2016-12-08 14:11:18 +00:00
//parse_map["grinning"] = []byte("😀")
//parse_map["grin"] = []byte("😁")
//parse_map["joy"] = []byte("😂")
2016-12-02 07:38:54 +00:00
// In a directory to stop it clashing with the other paths
2016-12-05 07:21:17 +00:00
http . HandleFunc ( "/static/" , route_static )
//http.HandleFunc("/static/", route_fstatic)
//fs_p := http.FileServer(http.Dir("./public"))
//http.Handle("/static/", http.StripPrefix("/static/",fs_p))
2016-12-02 15:03:31 +00:00
fs_u := http . FileServer ( http . Dir ( "./uploads" ) )
http . Handle ( "/uploads/" , http . StripPrefix ( "/uploads/" , fs_u ) )
2016-12-02 07:38:54 +00:00
http . HandleFunc ( "/overview/" , route_overview )
http . HandleFunc ( "/topics/create/" , route_topic_create )
http . HandleFunc ( "/topics/" , route_topics )
2016-12-03 13:45:08 +00:00
http . HandleFunc ( "/forums/" , route_forums )
http . HandleFunc ( "/forum/" , route_forum )
2016-12-02 07:38:54 +00:00
http . HandleFunc ( "/topic/create/submit/" , route_create_topic ) //POST
http . HandleFunc ( "/topic/" , route_topic_id )
http . HandleFunc ( "/reply/create/" , route_create_reply ) //POST
//http.HandleFunc("/reply/edit/", route_reply_edit) //POST
//http.HandleFunc("/reply/delete/", route_reply_delete) //POST
http . HandleFunc ( "/reply/edit/submit/" , route_reply_edit_submit ) //POST
http . HandleFunc ( "/reply/delete/submit/" , route_reply_delete_submit ) //POST
http . HandleFunc ( "/topic/edit/submit/" , route_edit_topic ) //POST
2016-12-03 10:25:39 +00:00
http . HandleFunc ( "/topic/delete/submit/" , route_delete_topic )
http . HandleFunc ( "/topic/stick/submit/" , route_stick_topic )
http . HandleFunc ( "/topic/unstick/submit/" , route_unstick_topic )
2016-12-02 07:38:54 +00:00
// Custom Pages
2016-12-02 09:29:45 +00:00
http . HandleFunc ( "/pages/" , route_custom_page )
2016-12-02 07:38:54 +00:00
// Accounts
http . HandleFunc ( "/accounts/login/" , route_login )
http . HandleFunc ( "/accounts/create/" , route_register )
http . HandleFunc ( "/accounts/logout/" , route_logout )
http . HandleFunc ( "/accounts/login/submit/" , route_login_submit ) // POST
http . HandleFunc ( "/accounts/create/submit/" , route_register_submit ) // POST
//http.HandleFunc("/accounts/list/", route_login) // Redirect /accounts/ and /user/ to here..
//http.HandleFunc("/accounts/create/full/", route_logout)
//http.HandleFunc("/user/edit/", route_logout)
http . HandleFunc ( "/user/edit/critical/" , route_account_own_edit_critical ) // Password & Email
http . HandleFunc ( "/user/edit/critical/submit/" , route_account_own_edit_critical_submit )
2016-12-03 04:50:35 +00:00
http . HandleFunc ( "/user/edit/avatar/" , route_account_own_edit_avatar )
2016-12-02 15:03:31 +00:00
http . HandleFunc ( "/user/edit/avatar/submit/" , route_account_own_edit_avatar_submit )
2016-12-03 08:09:40 +00:00
http . HandleFunc ( "/user/edit/username/" , route_account_own_edit_username )
http . HandleFunc ( "/user/edit/username/submit/" , route_account_own_edit_username_submit )
2016-12-07 09:34:09 +00:00
http . HandleFunc ( "/user/" , route_profile )
http . HandleFunc ( "/profile/reply/create/" , route_profile_reply_create )
http . HandleFunc ( "/profile/reply/edit/submit/" , route_profile_reply_edit_submit )
http . HandleFunc ( "/profile/reply/delete/submit/" , route_profile_reply_delete_submit )
2016-12-02 07:38:54 +00:00
//http.HandleFunc("/user/:id/edit/", route_logout)
2016-12-08 14:11:18 +00:00
http . HandleFunc ( "/users/ban/" , route_ban )
http . HandleFunc ( "/users/ban/submit/" , route_ban_submit )
http . HandleFunc ( "/users/unban/" , route_unban )
2016-12-04 10:44:28 +00:00
// Admin
http . HandleFunc ( "/panel/forums/" , route_panel_forums )
http . HandleFunc ( "/panel/forums/create/" , route_panel_forums_create_submit )
2016-12-06 10:26:48 +00:00
http . HandleFunc ( "/panel/forums/delete/" , route_panel_forums_delete )
http . HandleFunc ( "/panel/forums/delete/submit/" , route_panel_forums_delete_submit )
http . HandleFunc ( "/panel/forums/edit/submit/" , route_panel_forums_edit_submit )
2016-12-04 10:44:28 +00:00
2016-12-03 08:09:40 +00:00
http . HandleFunc ( "/" , default_route )
2016-12-02 07:38:54 +00:00
defer db . Close ( )
http . ListenAndServe ( ":8080" , nil )
}