1335 lines
34 KiB
Go
1335 lines
34 KiB
Go
package main
|
|
|
|
import "errors"
|
|
import "log"
|
|
import "fmt"
|
|
import "strconv"
|
|
import "bytes"
|
|
import "regexp"
|
|
import "strings"
|
|
import "time"
|
|
import "io"
|
|
import "os"
|
|
import "net/http"
|
|
import "html"
|
|
import "html/template"
|
|
import "database/sql"
|
|
import _ "github.com/go-sql-driver/mysql"
|
|
import "golang.org/x/crypto/bcrypt"
|
|
|
|
// A blank list to fill out that parameter in Page for routes which don't use it
|
|
var tList map[int]interface{}
|
|
|
|
// GET functions
|
|
func route_static(w http.ResponseWriter, r *http.Request){
|
|
//name := r.URL.Path[len("/static/"):]
|
|
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && static_files[r.URL.Path].Info.ModTime().Before(t.Add(1*time.Second)) {
|
|
w.WriteHeader(http.StatusNotModified)
|
|
return
|
|
}
|
|
h := w.Header()
|
|
h.Set("Last-Modified", static_files[r.URL.Path].FormattedModTime)
|
|
h.Set("Content-Type", static_files[r.URL.Path].Mimetype)
|
|
h.Set("Content-Length", strconv.FormatInt(static_files[r.URL.Path].Length, 10))
|
|
//http.ServeContent(w,r,r.URL.Path,static_files[r.URL.Path].Info.ModTime(),static_files[r.URL.Path])
|
|
//w.Write(static_files[r.URL.Path].Data)
|
|
io.Copy(w, bytes.NewReader(static_files[r.URL.Path].Data))
|
|
//io.CopyN(w, bytes.NewReader(static_files[r.URL.Path].Data), static_files[r.URL.Path].Length)
|
|
}
|
|
|
|
func route_fstatic(w http.ResponseWriter, r *http.Request){
|
|
http.ServeFile(w, r, r.URL.Path)
|
|
}
|
|
|
|
func route_overview(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
pi := Page{"Overview","overview",user,tList,0}
|
|
err := templates.ExecuteTemplate(w,"overview.html", pi)
|
|
if err != nil {
|
|
InternalError(err, w, r, user)
|
|
}
|
|
}
|
|
|
|
func route_custom_page(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
name := r.URL.Path[len("/pages/"):]
|
|
|
|
val, ok := custom_pages[name];
|
|
if ok {
|
|
pi := Page{"Page","page",user,tList,val}
|
|
templates.ExecuteTemplate(w,"custom_page.html", pi)
|
|
} else {
|
|
NotFound(w,r,user)
|
|
}
|
|
}
|
|
|
|
func route_topics(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
var(
|
|
topicList map[int]interface{}
|
|
currentID int
|
|
|
|
tid int
|
|
title string
|
|
content string
|
|
createdBy int
|
|
is_closed bool
|
|
sticky bool
|
|
createdAt string
|
|
parentID int
|
|
status string
|
|
name string
|
|
avatar string
|
|
)
|
|
topicList = make(map[int]interface{})
|
|
currentID = 0
|
|
|
|
rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC")
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
err := rows.Scan(&tid, &title, &content, &createdBy, &is_closed, &sticky, &createdAt, &parentID, &name, &avatar)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
if is_closed {
|
|
status = "closed"
|
|
} else {
|
|
status = "open"
|
|
}
|
|
if avatar != "" && avatar[0] == '.' {
|
|
avatar = "/uploads/avatar_" + strconv.Itoa(createdBy) + avatar
|
|
}
|
|
|
|
topicList[currentID] = TopicUser{tid, title, content, createdBy, is_closed, sticky, createdAt,parentID, status, name, avatar, ""}
|
|
currentID++
|
|
}
|
|
err = rows.Err()
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
pi := Page{"Topic List","topics",user,topicList,0}
|
|
err = templates.ExecuteTemplate(w,"topics.html", pi)
|
|
if err != nil {
|
|
InternalError(err, w, r, user)
|
|
}
|
|
}
|
|
|
|
func route_forum(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
var(
|
|
topicList map[int]interface{}
|
|
currentID int
|
|
|
|
tid int
|
|
title string
|
|
content string
|
|
createdBy int
|
|
is_closed bool
|
|
sticky bool
|
|
createdAt string
|
|
parentID int
|
|
status string
|
|
name string
|
|
avatar string
|
|
)
|
|
topicList = make(map[int]interface{})
|
|
currentID = 0
|
|
|
|
fid, err := strconv.Atoi(r.URL.Path[len("/forum/"):])
|
|
if err != nil {
|
|
LocalError("The provided ForumID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
_, ok := forums[fid]
|
|
if !ok {
|
|
NotFound(w,r,user)
|
|
return
|
|
}
|
|
|
|
rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid WHERE topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC", fid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
err := rows.Scan(&tid, &title, &content, &createdBy, &is_closed, &sticky, &createdAt, &parentID, &name, &avatar)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
if is_closed {
|
|
status = "closed"
|
|
} else {
|
|
status = "open"
|
|
}
|
|
if avatar != "" && avatar[0] == '.' {
|
|
avatar = "/uploads/avatar_" + strconv.Itoa(createdBy) + avatar
|
|
}
|
|
|
|
topicList[currentID] = TopicUser{tid, title, content, createdBy, is_closed, sticky, createdAt,parentID, status, name, avatar, ""}
|
|
currentID++
|
|
}
|
|
err = rows.Err()
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
pi := Page{forums[fid].Name,"forum",user,topicList,0}
|
|
err = templates.ExecuteTemplate(w,"forum.html", pi)
|
|
if err != nil {
|
|
InternalError(err, w, r, user)
|
|
}
|
|
}
|
|
|
|
func route_forums(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
var forumList map[int]interface{} = make(map[int]interface{})
|
|
currentID := 0
|
|
|
|
for _, forum := range forums {
|
|
if forum.Active {
|
|
forumList[currentID] = forum
|
|
currentID++
|
|
}
|
|
}
|
|
|
|
if len(forums) == 0 {
|
|
InternalError(errors.New("No forums"),w,r,user)
|
|
return
|
|
}
|
|
|
|
pi := Page{"Forum List","forums",user,forumList,0}
|
|
err := templates.ExecuteTemplate(w,"forums.html", pi)
|
|
if err != nil {
|
|
InternalError(err, w, r, user)
|
|
}
|
|
}
|
|
|
|
func route_topic_id(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
var(
|
|
err error
|
|
rid int
|
|
content string
|
|
replyContent string
|
|
replyCreatedBy int
|
|
replyCreatedByName string
|
|
replyCreatedAt string
|
|
replyLastEdit int
|
|
replyLastEditBy int
|
|
replyAvatar string
|
|
replyCss template.CSS
|
|
is_super_admin bool
|
|
group int
|
|
|
|
currentID int
|
|
replyList map[int]interface{}
|
|
)
|
|
replyList = make(map[int]interface{})
|
|
currentID = 0
|
|
topic := TopicUser{0,"","",0,false,false,"",0,"","","",no_css_tmpl}
|
|
|
|
topic.ID, err = strconv.Atoi(r.URL.Path[len("/topic/"):])
|
|
if err != nil {
|
|
LocalError("The provided TopicID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
// Get the topic..
|
|
//err = db.QueryRow("select title, content, createdBy, status, is_closed from topics where tid = ?", tid).Scan(&title, &content, &createdBy, &status, &is_closed)
|
|
err = db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, users.name, users.avatar, users.is_super_admin, users.group from topics left join users ON topics.createdBy = users.uid where tid = ?", topic.ID).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group)
|
|
if err == sql.ErrNoRows {
|
|
NotFound(w,r,user)
|
|
return
|
|
} else if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
topic.Content = template.HTML(parse_message(content))
|
|
if topic.Is_Closed {
|
|
topic.Status = "closed"
|
|
} else {
|
|
topic.Status = "open"
|
|
}
|
|
if topic.Avatar != "" && topic.Avatar[0] == '.' {
|
|
topic.Avatar = "/uploads/avatar_" + strconv.Itoa(topic.CreatedBy) + topic.Avatar
|
|
}
|
|
if is_super_admin || groups[group].Is_Admin {
|
|
topic.Css = staff_css_tmpl
|
|
}
|
|
|
|
// Get the replies..
|
|
//rows, err := db.Query("select rid, content, createdBy, createdAt from replies where tid = ?", tid)
|
|
rows, err := db.Query("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.is_super_admin, users.group from replies left join users ON replies.createdBy = users.uid where tid = ?", topic.ID)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &is_super_admin, &group)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
if is_super_admin || groups[group].Is_Admin {
|
|
replyCss = staff_css_tmpl
|
|
} else {
|
|
replyCss = no_css_tmpl
|
|
}
|
|
if replyAvatar != "" && replyAvatar[0] == '.' {
|
|
replyAvatar = "/uploads/avatar_" + strconv.Itoa(replyCreatedBy) + replyAvatar
|
|
}
|
|
|
|
replyList[currentID] = Reply{rid,topic.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss}
|
|
currentID++
|
|
}
|
|
err = rows.Err()
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
pi := Page{topic.Title,"topic",user,replyList,topic}
|
|
err = templates.ExecuteTemplate(w,"topic.html", pi)
|
|
if err != nil {
|
|
InternalError(err, w, r, user)
|
|
}
|
|
}
|
|
|
|
func route_topic_create(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
if user.Is_Banned {
|
|
Banned(w,r,user)
|
|
return
|
|
}
|
|
|
|
pi := Page{"Create Topic","create-topic",user,tList,0}
|
|
templates.ExecuteTemplate(w,"create-topic.html", pi)
|
|
}
|
|
|
|
// POST functions. Authorised users only.
|
|
func route_create_topic(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
LoginRequired(w,r,user)
|
|
return
|
|
}
|
|
if user.Is_Banned {
|
|
Banned(w,r,user)
|
|
return
|
|
}
|
|
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
success := 1
|
|
topic_name := html.EscapeString(r.PostFormValue("topic-name"))
|
|
|
|
res, err := create_topic_stmt.Exec(topic_name,html.EscapeString(r.PostFormValue("topic-content")),parse_message(html.EscapeString(r.PostFormValue("topic-content"))),user.ID)
|
|
if err != nil {
|
|
log.Print(err)
|
|
success = 0
|
|
}
|
|
|
|
lastId, err := res.LastInsertId()
|
|
if err != nil {
|
|
log.Print(err)
|
|
success = 0
|
|
}
|
|
|
|
_, err = update_forum_cache_stmt.Exec(topic_name, lastId, user.Name, user.ID, 1)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
if success != 1 {
|
|
errmsg := "Unable to create the topic"
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
} else {
|
|
http.Redirect(w, r, "/topic/" + strconv.FormatInt(lastId, 10), http.StatusSeeOther)
|
|
}
|
|
}
|
|
|
|
func route_create_reply(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
LoginRequired(w,r,user)
|
|
return
|
|
}
|
|
if user.Is_Banned {
|
|
Banned(w,r,user)
|
|
return
|
|
}
|
|
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
|
|
success := 1
|
|
tid, err := strconv.Atoi(r.PostFormValue("tid"))
|
|
if err != nil {
|
|
log.Print(err)
|
|
success = 0
|
|
|
|
errmsg := "Unable to create the reply"
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
_, err = create_reply_stmt.Exec(tid,html.EscapeString(r.PostFormValue("reply-content")),parse_message(html.EscapeString(r.PostFormValue("reply-content"))),user.ID)
|
|
if err != nil {
|
|
log.Print(err)
|
|
success = 0
|
|
}
|
|
|
|
var topic_name string
|
|
err = db.QueryRow("select title from topics where tid = ?", tid).Scan(&topic_name)
|
|
if err == sql.ErrNoRows {
|
|
log.Print(err)
|
|
success = 0
|
|
} else if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
_, err = update_forum_cache_stmt.Exec(topic_name, tid, user.Name, user.ID, 1)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
if success != 1 {
|
|
errmsg := "Unable to create the reply"
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
} else {
|
|
http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
|
}
|
|
}
|
|
|
|
func route_edit_topic(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
is_js := r.PostFormValue("js")
|
|
if is_js == "" {
|
|
is_js = "0"
|
|
}
|
|
|
|
if !user.Is_Admin {
|
|
NoPermissionsJSQ(w,r,user,is_js)
|
|
return
|
|
}
|
|
if user.Is_Banned {
|
|
BannedJSQ(w,r,user,is_js)
|
|
return
|
|
}
|
|
|
|
var tid int
|
|
tid, err = strconv.Atoi(r.URL.Path[len("/topic/edit/submit/"):])
|
|
if err != nil {
|
|
LocalErrorJSQ("The provided TopicID is not a valid number.",w,r,user,is_js)
|
|
return
|
|
}
|
|
|
|
topic_name := r.PostFormValue("topic_name")
|
|
topic_status := r.PostFormValue("topic_status")
|
|
//log.Print(topic_name)
|
|
//log.Print(topic_status)
|
|
var is_closed bool
|
|
if topic_status == "closed" {
|
|
is_closed = true
|
|
} else {
|
|
is_closed = false
|
|
}
|
|
topic_content := html.EscapeString(r.PostFormValue("topic_content"))
|
|
//log.Print(topic_content)
|
|
_, err = edit_topic_stmt.Exec(topic_name, topic_content, parse_message(topic_content), is_closed, tid)
|
|
if err != nil {
|
|
InternalErrorJSQ(err,w,r,user,is_js)
|
|
return
|
|
}
|
|
|
|
if is_js == "0" {
|
|
http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
|
} else {
|
|
fmt.Fprintf(w,"{'success': '1'}")
|
|
}
|
|
}
|
|
|
|
func route_delete_topic(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Is_Admin {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/delete/submit/"):])
|
|
if err != nil {
|
|
LocalError("The provided TopicID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
err = db.QueryRow("SELECT tid from topics where tid = ?", tid).Scan(&tid)
|
|
if err == sql.ErrNoRows {
|
|
LocalError("The topic you tried to delete doesn't exist.",w,r,user)
|
|
return
|
|
} else if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
_, err = delete_topic_stmt.Exec(tid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
log.Print("The topic '" + strconv.Itoa(tid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".")
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
}
|
|
|
|
func route_stick_topic(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Is_Admin {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/stick/submit/"):])
|
|
if err != nil {
|
|
LocalError("The provided TopicID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
_, err = stick_topic_stmt.Exec(tid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
|
}
|
|
|
|
func route_unstick_topic(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Is_Admin {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/unstick/submit/"):])
|
|
if err != nil {
|
|
LocalError("The provided TopicID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
_, err = unstick_topic_stmt.Exec(tid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
|
}
|
|
|
|
func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
|
|
is_js := r.PostFormValue("js")
|
|
if is_js == "" {
|
|
is_js = "0"
|
|
}
|
|
|
|
if !user.Is_Admin {
|
|
NoPermissionsJSQ(w,r,user,is_js)
|
|
return
|
|
}
|
|
|
|
rid, err := strconv.Atoi(r.URL.Path[len("/reply/edit/submit/"):])
|
|
if err != nil {
|
|
LocalError("The provided Reply ID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
content := html.EscapeString(r.PostFormValue("edit_item"))
|
|
_, err = edit_reply_stmt.Exec(content, parse_message(content), rid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
// Get the Reply ID..
|
|
var tid int
|
|
err = db.QueryRow("select tid from replies where rid = ?", rid).Scan(&tid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
if is_js == "0" {
|
|
http.Redirect(w,r, "/topic/" + strconv.Itoa(tid) + "#reply-" + strconv.Itoa(rid), http.StatusSeeOther)
|
|
} else {
|
|
fmt.Fprintf(w,"{'success': '1'}")
|
|
}
|
|
}
|
|
|
|
func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
|
|
is_js := r.PostFormValue("is_js")
|
|
if is_js == "" {
|
|
is_js = "0"
|
|
}
|
|
|
|
if !user.Is_Admin {
|
|
NoPermissionsJSQ(w,r,user,is_js)
|
|
return
|
|
}
|
|
|
|
rid, err := strconv.Atoi(r.URL.Path[len("/reply/delete/submit/"):])
|
|
if err != nil {
|
|
LocalErrorJSQ("The provided Reply ID is not a valid number.",w,r,user,is_js)
|
|
return
|
|
}
|
|
|
|
var tid int
|
|
err = db.QueryRow("SELECT tid from replies where rid = ?", rid).Scan(&tid)
|
|
if err == sql.ErrNoRows {
|
|
LocalErrorJSQ("The reply you tried to delete doesn't exist.",w,r,user,is_js)
|
|
return
|
|
} else if err != nil {
|
|
InternalErrorJSQ(err,w,r,user,is_js)
|
|
return
|
|
}
|
|
|
|
_, err = delete_reply_stmt.Exec(rid)
|
|
if err != nil {
|
|
InternalErrorJSQ(err,w,r,user,is_js)
|
|
return
|
|
}
|
|
log.Print("The reply '" + strconv.Itoa(rid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".")
|
|
|
|
if is_js == "0" {
|
|
//http.Redirect(w,r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
|
} else {
|
|
fmt.Fprintf(w,"{'success': '1'}")
|
|
}
|
|
}
|
|
|
|
func route_account_own_edit_critical(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
errmsg := "You need to login to edit your own account."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
pi := Page{"Edit Password","account-own-edit",user,tList,0}
|
|
templates.ExecuteTemplate(w,"account-own-edit.html", pi)
|
|
}
|
|
|
|
func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
errmsg := "You need to login to edit your own account."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
|
|
var real_password string
|
|
var salt string
|
|
current_password := r.PostFormValue("account-current-password")
|
|
new_password := r.PostFormValue("account-new-password")
|
|
confirm_password := r.PostFormValue("account-confirm-password")
|
|
|
|
err = get_password_stmt.QueryRow(user.ID).Scan(&real_password, &salt)
|
|
if err == sql.ErrNoRows {
|
|
pi := Page{"Error","error",user,tList,"Your account doesn't exist."}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
} else if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
current_password = current_password + salt
|
|
err = bcrypt.CompareHashAndPassword([]byte(real_password), []byte(current_password))
|
|
if err == bcrypt.ErrMismatchedHashAndPassword {
|
|
pi := Page{"Error","error",user,tList,"That's not the correct password."}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
} else if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
if new_password != confirm_password {
|
|
pi := Page{"Error","error",user,tList,"The two passwords don't match."}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
SetPassword(user.ID, new_password)
|
|
|
|
// Log the user out as a safety precaution
|
|
_, err = logout_stmt.Exec(user.ID)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
pi := Page{"Edit Password","account-own-edit-success",user,tList,0}
|
|
templates.ExecuteTemplate(w,"account-own-edit-success.html", pi)
|
|
}
|
|
|
|
func route_account_own_edit_avatar(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
errmsg := "You need to login to edit your own account."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
pi := Page{"Edit Avatar","account-own-edit-avatar",user,tList,0}
|
|
templates.ExecuteTemplate(w,"account-own-edit-avatar.html", pi)
|
|
}
|
|
|
|
func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request) {
|
|
if r.ContentLength > int64(max_request_size) {
|
|
http.Error(w, "request too large", http.StatusExpectationFailed)
|
|
return
|
|
}
|
|
r.Body = http.MaxBytesReader(w, r.Body, int64(max_request_size))
|
|
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
errmsg := "You need to login to edit your own account."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
err := r.ParseMultipartForm(int64(max_request_size))
|
|
if err != nil {
|
|
LocalError("Upload failed", w, r, user)
|
|
return
|
|
}
|
|
|
|
var filename string = ""
|
|
var ext string
|
|
for _, fheaders := range r.MultipartForm.File {
|
|
for _, hdr := range fheaders {
|
|
infile, err := hdr.Open();
|
|
if err != nil {
|
|
LocalError("Upload failed", w, r, user)
|
|
return
|
|
}
|
|
defer infile.Close()
|
|
|
|
// We don't want multiple files
|
|
if filename != "" {
|
|
if filename != hdr.Filename {
|
|
os.Remove("./uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext)
|
|
LocalError("You may only upload one avatar", w, r, user)
|
|
return
|
|
}
|
|
} else {
|
|
filename = hdr.Filename
|
|
}
|
|
|
|
if ext == "" {
|
|
extarr := strings.Split(hdr.Filename,".")
|
|
if len(extarr) < 2 {
|
|
LocalError("Bad file", w, r, user)
|
|
return
|
|
}
|
|
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 = 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)
|
|
return
|
|
}
|
|
defer outfile.Close()
|
|
|
|
_, 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))
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext
|
|
|
|
pi := Page{"Edit Avatar","account-own-edit-avatar-success",user,tList,0}
|
|
templates.ExecuteTemplate(w,"account-own-edit-avatar-success.html", pi)
|
|
}
|
|
|
|
func route_account_own_edit_username(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
errmsg := "You need to login to edit your own account."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
pi := Page{"Edit Username","account-own-edit-username",user,tList,user.Name}
|
|
templates.ExecuteTemplate(w,"account-own-edit-username.html", pi)
|
|
}
|
|
|
|
func route_account_own_edit_username_submit(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
errmsg := "You need to login to edit your own account."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
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 {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
user.Name = new_username
|
|
|
|
pi := Page{"Edit Username","account-own-edit-username",user,tList,user.Name}
|
|
templates.ExecuteTemplate(w,"account-own-edit-username.html", pi)
|
|
}
|
|
|
|
func route_logout(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Loggedin {
|
|
errmsg := "You can't logout without logging in first."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
_, err := logout_stmt.Exec(user.ID)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
http.Redirect(w,r, "/", http.StatusSeeOther)
|
|
}
|
|
|
|
func route_login(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if user.Loggedin {
|
|
errmsg := "You're already logged in."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
pi := Page{"Login","login",user,tList,0}
|
|
templates.ExecuteTemplate(w,"login.html", pi)
|
|
}
|
|
|
|
func route_login_submit(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if user.Loggedin {
|
|
errmsg := "You're already logged in."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
|
|
var uid int
|
|
var real_password string
|
|
var salt string
|
|
var session string
|
|
username := html.EscapeString(r.PostFormValue("username"))
|
|
//log.Print("Username: " + username)
|
|
password := r.PostFormValue("password")
|
|
//log.Print("Password: " + password)
|
|
|
|
err = login_stmt.QueryRow(username).Scan(&uid, &username, &real_password, &salt)
|
|
if err == sql.ErrNoRows {
|
|
errmsg := "That username doesn't exist."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
} else if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
// Emergency password reset mechanism..
|
|
if salt == "" {
|
|
if password != real_password {
|
|
errmsg := "That's not the correct password."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
// Re-encrypt the password
|
|
SetPassword(uid, password)
|
|
} else { // Normal login..
|
|
password = password + salt
|
|
//hashed_password, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
//log.Print("Hashed: " + string(hashed_password))
|
|
//log.Print("Real: " + real_password)
|
|
//if string(hashed_password) != real_password {
|
|
err := bcrypt.CompareHashAndPassword([]byte(real_password), []byte(password))
|
|
if err == bcrypt.ErrMismatchedHashAndPassword {
|
|
errmsg := "That's not the correct password."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
} else if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
}
|
|
|
|
session, err = GenerateSafeString(sessionLength)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
_, err = update_session_stmt.Exec(session, uid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
//log.Print("Successful Login")
|
|
//log.Print("Session: " + session)
|
|
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)
|
|
http.Redirect(w,r, "/", http.StatusSeeOther)
|
|
}
|
|
|
|
func route_register(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if user.Loggedin {
|
|
errmsg := "You're already logged in."
|
|
pi := Page{"Error","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
pi := Page{"Registration","register",user,tList,0}
|
|
templates.ExecuteTemplate(w,"register.html", pi)
|
|
}
|
|
|
|
func route_register_submit(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
|
|
username := html.EscapeString(r.PostFormValue("username"))
|
|
password := r.PostFormValue("password")
|
|
confirm_password := r.PostFormValue("confirm_password")
|
|
log.Print("Registration Attempt! Username: " + username)
|
|
|
|
// Do the two inputted passwords match..?
|
|
if password != confirm_password {
|
|
errmsg := "The two passwords don't match."
|
|
pi := Page{"Password Mismatch","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
// Is this username already taken..?
|
|
err = username_exists_stmt.QueryRow(username).Scan(&username)
|
|
if err != nil && err != sql.ErrNoRows {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
} else if err != sql.ErrNoRows {
|
|
errmsg := "This username isn't available. Try another."
|
|
pi := Page{"Username Taken","error",user,tList,errmsg}
|
|
|
|
var b bytes.Buffer
|
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
|
errpage := b.String()
|
|
w.WriteHeader(500)
|
|
fmt.Fprintln(w,errpage)
|
|
return
|
|
}
|
|
|
|
salt, err := GenerateSafeString(saltLength)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
session, err := GenerateSafeString(sessionLength)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
password = password + salt
|
|
hashed_password, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
res, err := register_stmt.Exec(username,string(hashed_password),salt,session)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
lastId, err := res.LastInsertId()
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
cookie := http.Cookie{Name: "uid",Value: strconv.FormatInt(lastId, 10),Path: "/",MaxAge: year}
|
|
http.SetCookie(w,&cookie)
|
|
cookie = http.Cookie{Name: "session",Value: session,Path: "/",MaxAge: year}
|
|
http.SetCookie(w,&cookie)
|
|
http.Redirect(w,r, "/", http.StatusSeeOther)
|
|
}
|
|
|
|
func route_panel_forums(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
if !user.Is_Admin {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
|
|
var forumList map[int]interface{} = make(map[int]interface{})
|
|
currentID := 0
|
|
|
|
for _, forum := range forums {
|
|
if forum.ID > -1 {
|
|
forumList[currentID] = forum
|
|
currentID++
|
|
}
|
|
}
|
|
|
|
pi := Page{"Forum Manager","panel-forums",user,forumList,0}
|
|
templates.ExecuteTemplate(w,"panel-forums.html", pi)
|
|
}
|
|
|
|
func route_panel_forums_create_submit(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
if !user.Is_Admin {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
if r.FormValue("session") != user.Session {
|
|
SecurityError(w,r,user)
|
|
return
|
|
}
|
|
|
|
fname := r.PostFormValue("forum-name")
|
|
res, err := create_forum_stmt.Exec(fname)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
lastId, err := res.LastInsertId()
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
forums[int(lastId)] = Forum{int(lastId),fname,true,"",0,"",0,""}
|
|
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
|
|
}
|
|
|
|
func route_panel_forums_delete(w http.ResponseWriter, r *http.Request){
|
|
user := SessionCheck(w,r)
|
|
if !user.Is_Admin {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
if r.FormValue("session") != user.Session {
|
|
SecurityError(w,r,user)
|
|
return
|
|
}
|
|
fid, err := strconv.Atoi(r.URL.Path[len("/panel/forums/delete/"):])
|
|
if err != nil {
|
|
LocalError("The provided Forum ID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
_, ok := forums[fid];
|
|
if !ok {
|
|
LocalError("The forum you're trying to delete doesn't exist.",w,r,user)
|
|
return
|
|
}
|
|
|
|
confirm_msg := "Are you sure you want to delete the '" + forums[fid].Name + "' forum?"
|
|
yousure := AreYouSure{"/panel/forums/delete/submit/" + strconv.Itoa(fid),confirm_msg}
|
|
|
|
pi := Page{"Delete Forum","panel-forums-delete",user,tList,yousure}
|
|
templates.ExecuteTemplate(w,"areyousure.html", pi)
|
|
}
|
|
|
|
func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Is_Admin {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
if r.FormValue("session") != user.Session {
|
|
SecurityError(w,r,user)
|
|
return
|
|
}
|
|
|
|
fid, err := strconv.Atoi(r.URL.Path[len("/panel/forums/delete/submit/"):])
|
|
if err != nil {
|
|
LocalError("The provided Forum ID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
_, ok := forums[fid];
|
|
if !ok {
|
|
LocalError("The forum you're trying to delete doesn't exist.",w,r,user)
|
|
return
|
|
}
|
|
|
|
_, err = delete_forum_stmt.Exec(fid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
|
|
// Remove this forum from the forum cache
|
|
delete(forums,fid);
|
|
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
|
|
}
|
|
|
|
func route_panel_forums_edit_submit(w http.ResponseWriter, r *http.Request) {
|
|
user := SessionCheck(w,r)
|
|
if !user.Is_Admin {
|
|
NoPermissions(w,r,user)
|
|
return
|
|
}
|
|
|
|
err := r.ParseForm()
|
|
if err != nil {
|
|
LocalError("Bad Form", w, r, user)
|
|
return
|
|
}
|
|
if r.FormValue("session") != user.Session {
|
|
SecurityError(w,r,user)
|
|
return
|
|
}
|
|
|
|
fid, err := strconv.Atoi(r.URL.Path[len("/panel/forums/edit/submit/"):])
|
|
if err != nil {
|
|
LocalError("The provided Forum ID is not a valid number.",w,r,user)
|
|
return
|
|
}
|
|
|
|
forum_name := r.PostFormValue("edit_item")
|
|
|
|
forum, ok := forums[fid];
|
|
if !ok {
|
|
LocalError("The forum you're trying to edit doesn't exist.",w,r,user)
|
|
return
|
|
}
|
|
|
|
_, err = update_forum_stmt.Exec(forum_name, fid)
|
|
if err != nil {
|
|
InternalError(err,w,r,user)
|
|
return
|
|
}
|
|
forum.Name = forum_name
|
|
forums[fid] = forum
|
|
|
|
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
|
|
} |