Added the Rez Image Resizer as a dependency to be used later.

Is Codebeat fixed now?
Fixed a data race in PreRoute and refactored away the duplicate IP Address loads.
Renamed some of the variables in the query generator.
Slight bit more progress on Cosora.
This commit is contained in:
Azareal 2017-11-10 00:16:15 +00:00
parent 34ca7de946
commit f8e892da20
22 changed files with 266 additions and 272 deletions

View File

@ -1,10 +1,10 @@
/public/trumbowyg/* /public/trumbowyg/**
/public/jquery-emojiarea/* /public/jquery-emojiarea/**
/public/font-awesome-4.7.0/* /public/font-awesome-4.7.0/**
/public/jquery-3.1.1.min.js /public/jquery-3.1.1.min.js
/public/EQCSS.min.js /public/EQCSS.min.js
/public/EQCSS.js /public/EQCSS.js
/schema/* /schema/**
template_list.go template_list.go
template_forum.go template_forum.go

View File

@ -25,6 +25,9 @@ go get -u github.com/robertkrimen/otto
echo "Installing the Riot Search Engine" echo "Installing the Riot Search Engine"
go get -u github.com/robertkrimen/otto go get -u github.com/robertkrimen/otto
echo "Installing the Rez Image Resizer"
go get -u github.com/bamiaux/rez
echo "Building the installer" echo "Building the installer"
cd ./install cd ./install

View File

@ -78,6 +78,13 @@ if %errorlevel% neq 0 (
exit /b %errorlevel% exit /b %errorlevel%
) )
echo Installing the Rez Image Resizer
go get -u github.com/bamiaux/rez
if %errorlevel% neq 0 (
pause
exit /b %errorlevel%
)
echo Building the installer echo Building the installer
go generate go generate

View File

@ -6,7 +6,6 @@ import (
"html" "html"
"io" "io"
"log" "log"
"net"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -134,12 +133,7 @@ func routeTopicCreateSubmit(w http.ResponseWriter, r *http.Request, user User) R
topicName := html.EscapeString(r.PostFormValue("topic-name")) topicName := html.EscapeString(r.PostFormValue("topic-name"))
content := html.EscapeString(preparseMessage(r.PostFormValue("topic-content"))) content := html.EscapeString(preparseMessage(r.PostFormValue("topic-content")))
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) tid, err := topics.Create(fid, topicName, content, user.ID, user.LastIP)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
tid, err := topics.Create(fid, topicName, content, user.ID, ipaddress)
if err != nil { if err != nil {
switch err { switch err {
case ErrNoRows: case ErrNoRows:
@ -339,12 +333,7 @@ func routeCreateReply(w http.ResponseWriter, r *http.Request, user User) RouteEr
} }
content := preparseMessage(html.EscapeString(r.PostFormValue("reply-content"))) content := preparseMessage(html.EscapeString(r.PostFormValue("reply-content")))
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) _, err = rstore.Create(topic, content, user.LastIP, user.ID)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
_, err = rstore.Create(topic, content, ipaddress, user.ID)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
@ -537,13 +526,8 @@ func routeProfileReplyCreate(w http.ResponseWriter, r *http.Request, user User)
return LocalError("Invalid UID", w, r, user) return LocalError("Invalid UID", w, r, user)
} }
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
content := html.EscapeString(preparseMessage(r.PostFormValue("reply-content"))) content := html.EscapeString(preparseMessage(r.PostFormValue("reply-content")))
_, err = prstore.Create(uid, content, user.ID, ipaddress) _, err = prstore.Create(uid, content, user.ID, user.LastIP)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }

View File

@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"html" "html"
"log" "log"
"net"
"net/http" "net/http"
"strconv" "strconv"
"time" "time"
@ -113,11 +112,7 @@ func routeDeleteTopic(w http.ResponseWriter, r *http.Request, user User) RouteEr
return InternalErrorJSQ(err, w, r, isJs) return InternalErrorJSQ(err, w, r, isJs)
} }
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) err = addModLog("delete", tid, "topic", user.LastIP, user.ID)
if err != nil {
return LocalErrorJSQ("Bad IP", w, r, user, isJs)
}
err = addModLog("delete", tid, "topic", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalErrorJSQ(err, w, r, isJs) return InternalErrorJSQ(err, w, r, isJs)
} }
@ -161,16 +156,11 @@ func routeStickTopic(w http.ResponseWriter, r *http.Request, user User) RouteErr
return InternalError(err, w, r) return InternalError(err, w, r)
} }
// ! - Can we use user.LastIP here? It might be racey, if another thread mutates it... We need to fix this. err = addModLog("stick", tid, "topic", user.LastIP, user.ID)
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
err = addModLog("stick", tid, "topic", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
err = topic.CreateActionReply("stick", ipaddress, user) err = topic.CreateActionReply("stick", user.LastIP, user)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
@ -205,15 +195,11 @@ func routeUnstickTopic(w http.ResponseWriter, r *http.Request, user User) RouteE
return InternalError(err, w, r) return InternalError(err, w, r)
} }
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) err = addModLog("unstick", tid, "topic", user.LastIP, user.ID)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
err = addModLog("unstick", tid, "topic", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
err = topic.CreateActionReply("unstick", ipaddress, user) err = topic.CreateActionReply("unstick", user.LastIP, user)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
@ -268,16 +254,11 @@ func routeLockTopic(w http.ResponseWriter, r *http.Request, user User) RouteErro
return InternalErrorJSQ(err, w, r, isJs) return InternalErrorJSQ(err, w, r, isJs)
} }
// ! - Can we use user.LastIP here? It might be racey, if another thread mutates it... We need to fix this. err = addModLog("lock", tid, "topic", user.LastIP, user.ID)
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return LocalErrorJSQ("Bad IP", w, r, user, isJs)
}
err = addModLog("lock", tid, "topic", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalErrorJSQ(err, w, r, isJs) return InternalErrorJSQ(err, w, r, isJs)
} }
err = topic.CreateActionReply("lock", ipaddress, user) err = topic.CreateActionReply("lock", user.LastIP, user)
if err != nil { if err != nil {
return InternalErrorJSQ(err, w, r, isJs) return InternalErrorJSQ(err, w, r, isJs)
} }
@ -316,16 +297,11 @@ func routeUnlockTopic(w http.ResponseWriter, r *http.Request, user User) RouteEr
return InternalError(err, w, r) return InternalError(err, w, r)
} }
// ! - Can we use user.LastIP here? It might be racey, if another thread mutates it... We need to fix this. err = addModLog("unlock", tid, "topic", user.LastIP, user.ID)
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
err = addModLog("unlock", tid, "topic", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
err = topic.CreateActionReply("unlock", ipaddress, user) err = topic.CreateActionReply("unlock", user.LastIP, user)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
@ -447,11 +423,7 @@ func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) R
return InternalErrorJSQ(err, w, r, isJs) return InternalErrorJSQ(err, w, r, isJs)
} }
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) err = addModLog("delete", reply.ParentID, "reply", user.LastIP, user.ID)
if err != nil {
return LocalErrorJSQ("Bad IP", w, r, user, isJs)
}
err = addModLog("delete", reply.ParentID, "reply", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalErrorJSQ(err, w, r, isJs) return InternalErrorJSQ(err, w, r, isJs)
} }
@ -694,11 +666,7 @@ func routeBanSubmit(w http.ResponseWriter, r *http.Request, user User) RouteErro
return InternalError(err, w, r) return InternalError(err, w, r)
} }
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) err = addModLog("ban", uid, "user", user.LastIP, user.ID)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
err = addModLog("ban", uid, "user", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
@ -740,11 +708,7 @@ func routeUnban(w http.ResponseWriter, r *http.Request, user User) RouteError {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) err = addModLog("unban", uid, "user", user.LastIP, user.ID)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
err = addModLog("unban", uid, "user", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }
@ -781,11 +745,7 @@ func routeActivate(w http.ResponseWriter, r *http.Request, user User) RouteError
return InternalError(err, w, r) return InternalError(err, w, r)
} }
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) err = addModLog("activate", targetUser.ID, "user", user.LastIP, user.ID)
if err != nil {
return LocalError("Bad IP", w, r, user)
}
err = addModLog("activate", targetUser.ID, "user", ipaddress, user.ID)
if err != nil { if err != nil {
return InternalError(err, w, r) return InternalError(err, w, r)
} }

View File

@ -90,6 +90,7 @@ type Perms struct {
// Forum permissions // Forum permissions
ViewTopic bool ViewTopic bool
//ViewOwnTopic bool
LikeItem bool LikeItem bool
CreateTopic bool CreateTopic bool
EditTopic bool EditTopic bool
@ -109,6 +110,7 @@ type Perms struct {
/* Inherit from group permissions for ones we don't have */ /* Inherit from group permissions for ones we don't have */
type ForumPerms struct { type ForumPerms struct {
ViewTopic bool ViewTopic bool
//ViewOwnTopic bool
LikeItem bool LikeItem bool
CreateTopic bool CreateTopic bool
EditTopic bool EditTopic bool

View File

@ -81,12 +81,12 @@ func processJoiner(joinstr string) (joiner []DB_Joiner) {
outjoin.Operator, parseOffset = getOperator(segment, parseOffset+1) outjoin.Operator, parseOffset = getOperator(segment, parseOffset+1)
right, parseOffset = getIdentifier(segment, parseOffset+1) right, parseOffset = getIdentifier(segment, parseOffset+1)
left_column := strings.Split(left, ".") leftColumn := strings.Split(left, ".")
right_column := strings.Split(right, ".") rightColumn := strings.Split(right, ".")
outjoin.LeftTable = strings.TrimSpace(left_column[0]) outjoin.LeftTable = strings.TrimSpace(leftColumn[0])
outjoin.RightTable = strings.TrimSpace(right_column[0]) outjoin.RightTable = strings.TrimSpace(rightColumn[0])
outjoin.LeftColumn = strings.TrimSpace(left_column[1]) outjoin.LeftColumn = strings.TrimSpace(leftColumn[1])
outjoin.RightColumn = strings.TrimSpace(right_column[1]) outjoin.RightColumn = strings.TrimSpace(rightColumn[1])
joiner = append(joiner, outjoin) joiner = append(joiner, outjoin)
} }
@ -102,14 +102,14 @@ func processWhere(wherestr string) (where []DB_Where) {
var buffer string var buffer string
var optype int // 0: None, 1: Number, 2: Column, 3: Function, 4: String, 5: Operator 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 var tmpWhere DB_Where
segment += ")" segment += ")"
for i := 0; i < len(segment); i++ { for i := 0; i < len(segment); i++ {
char := segment[i] char := segment[i]
//fmt.Println("optype",optype) //fmt.Println("optype", optype)
switch optype { switch optype {
case 0: // unknown case 0: // unknown
//fmt.Println("case 0:",char,string(char)) //fmt.Println("case 0:", char, string(char))
if '0' <= char && char <= '9' { if '0' <= char && char <= '9' {
optype = 1 optype = 1
buffer = string(char) buffer = string(char)
@ -119,12 +119,12 @@ func processWhere(wherestr string) (where []DB_Where) {
} else if char == '\'' { } else if char == '\'' {
optype = 4 optype = 4
buffer = "" buffer = ""
} else if _is_op_byte(char) { } else if isOpByte(char) {
optype = 5 optype = 5
buffer = string(char) buffer = string(char)
} else if char == '?' { } else if char == '?' {
//fmt.Println("Expr:","?") //fmt.Println("Expr:","?")
tmp_where.Expr = append(tmp_where.Expr, DB_Token{"?", "substitute"}) tmpWhere.Expr = append(tmpWhere.Expr, DB_Token{"?", "substitute"})
} }
case 1: // number case 1: // number
if '0' <= char && char <= '9' { if '0' <= char && char <= '9' {
@ -133,7 +133,7 @@ func processWhere(wherestr string) (where []DB_Where) {
optype = 0 optype = 0
i-- i--
//fmt.Println("Expr:",buffer) //fmt.Println("Expr:",buffer)
tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "number"}) tmpWhere.Expr = append(tmpWhere.Expr, DB_Token{buffer, "number"})
} }
case 2: // column case 2: // column
if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '.' || char == '_' { if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '.' || char == '_' {
@ -144,23 +144,23 @@ func processWhere(wherestr string) (where []DB_Where) {
} else { } else {
optype = 0 optype = 0
i-- i--
//fmt.Println("Expr:",buffer) //fmt.Println("Expr:", buffer)
tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "column"}) tmpWhere.Expr = append(tmpWhere.Expr, DB_Token{buffer, "column"})
} }
case 3: // function case 3: // function
var preI = i var preI = i
//fmt.Println("buffer",buffer) //fmt.Println("buffer", buffer)
//fmt.Println("len(halves)",len(halves[1])) //fmt.Println("len(halves)", len(halves[1]))
//fmt.Println("preI",string(halves[1][preI])) //fmt.Println("preI", string(halves[1][preI]))
//fmt.Println("msg prior to preI",halves[1][0:preI]) //fmt.Println("msg prior to preI", halves[1][0:preI])
i = skipFunctionCall(segment, i-1) i = skipFunctionCall(segment, i-1)
//fmt.Println("i",i) //fmt.Println("i",i)
//fmt.Println("msg prior to i-1",halves[1][0:i-1]) //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-1)", string(halves[1][i-1]))
//fmt.Println("string(i)",string(halves[1][i])) //fmt.Println("string(i)", string(halves[1][i]))
buffer += segment[preI:i] + string(segment[i]) buffer += segment[preI:i] + string(segment[i])
//fmt.Println("Expr:",buffer) //fmt.Println("Expr:",buffer)
tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "function"}) tmpWhere.Expr = append(tmpWhere.Expr, DB_Token{buffer, "function"})
optype = 0 optype = 0
case 4: // string case 4: // string
if char != '\'' { if char != '\'' {
@ -168,22 +168,22 @@ func processWhere(wherestr string) (where []DB_Where) {
} else { } else {
optype = 0 optype = 0
//fmt.Println("Expr:",buffer) //fmt.Println("Expr:",buffer)
tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "string"}) tmpWhere.Expr = append(tmpWhere.Expr, DB_Token{buffer, "string"})
} }
case 5: // operator case 5: // operator
if _is_op_byte(char) { if isOpByte(char) {
buffer += string(char) buffer += string(char)
} else { } else {
optype = 0 optype = 0
i-- i--
//fmt.Println("Expr:",buffer) //fmt.Println("Expr:",buffer)
tmp_where.Expr = append(tmp_where.Expr, DB_Token{buffer, "operator"}) tmpWhere.Expr = append(tmpWhere.Expr, DB_Token{buffer, "operator"})
} }
default: default:
panic("Bad optype in _process_where") panic("Bad optype in _process_where")
} }
} }
where = append(where, tmp_where) where = append(where, tmpWhere)
} }
return where return where
} }
@ -241,7 +241,7 @@ func processSet(setstr string) (setter []DB_Setter) {
} else if char == '\'' { } else if char == '\'' {
optype = 4 optype = 4
buffer = "" buffer = ""
} else if _is_op_byte(char) { } else if isOpByte(char) {
optype = 5 optype = 5
buffer = string(char) buffer = string(char)
} else if char == '?' { } else if char == '?' {
@ -289,20 +289,20 @@ func processSet(setstr string) (setter []DB_Setter) {
buffer += string(char) buffer += string(char)
} else { } else {
optype = 0 optype = 0
//fmt.Println("Expr:",buffer) //fmt.Println("Expr:", buffer)
tmpSetter.Expr = append(tmpSetter.Expr, DB_Token{buffer, "string"}) tmpSetter.Expr = append(tmpSetter.Expr, DB_Token{buffer, "string"})
} }
case 5: // operator case 5: // operator
if _is_op_byte(char) { if isOpByte(char) {
buffer += string(char) buffer += string(char)
} else { } else {
optype = 0 optype = 0
i-- i--
//fmt.Println("Expr:",buffer) //fmt.Println("Expr:", buffer)
tmpSetter.Expr = append(tmpSetter.Expr, DB_Token{buffer, "operator"}) tmpSetter.Expr = append(tmpSetter.Expr, DB_Token{buffer, "operator"})
} }
default: default:
panic("Bad optype in _process_set") panic("Bad optype in processSet")
} }
} }
setter = append(setter, tmpSetter) setter = append(setter, tmpSetter)
@ -322,11 +322,11 @@ func processLimit(limitstr string) (limiter DB_Limit) {
return limiter return limiter
} }
func _is_op_byte(char byte) bool { func isOpByte(char byte) bool {
return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/' return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/'
} }
func _is_op_rune(char rune) bool { func isOpRune(char rune) bool {
return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/' return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/'
} }
@ -375,7 +375,7 @@ func getIdentifier(segment string, startOffset int) (out string, i int) {
i = skipFunctionCall(segment, i) i = skipFunctionCall(segment, i)
return strings.TrimSpace(segment[startOffset:i]), (i - 1) return strings.TrimSpace(segment[startOffset:i]), (i - 1)
} }
if (segment[i] == ' ' || _is_op_byte(segment[i])) && i != startOffset { if (segment[i] == ' ' || isOpByte(segment[i])) && i != startOffset {
return strings.TrimSpace(segment[startOffset:i]), (i - 1) return strings.TrimSpace(segment[startOffset:i]), (i - 1)
} }
} }
@ -386,7 +386,7 @@ func getOperator(segment string, startOffset int) (out string, i int) {
segment = strings.TrimSpace(segment) segment = strings.TrimSpace(segment)
segment += " " // Avoid overflow bugs with slicing segment += " " // Avoid overflow bugs with slicing
for i = startOffset; i < len(segment); i++ { for i = startOffset; i < len(segment); i++ {
if !_is_op_byte(segment[i]) && i != startOffset { if !isOpByte(segment[i]) && i != startOffset {
return strings.TrimSpace(segment[startOffset:i]), (i - 1) return strings.TrimSpace(segment[startOffset:i]), (i - 1)
} }
} }

38
router_gen/route_impl.go Normal file
View File

@ -0,0 +1,38 @@
package main
type RouteImpl struct {
Name string
Path string
Vars []string
RunBefore []Runnable
}
type Runnable struct {
Contents string
Literal bool
}
func addRoute(route *RouteImpl) {
routeList = append(routeList, route)
}
func (route *RouteImpl) Before(item string, literal ...bool) *RouteImpl {
var litItem bool
if len(literal) > 0 {
litItem = literal[0]
}
route.RunBefore = append(route.RunBefore, Runnable{item, litItem})
return route
}
func addRouteGroup(routeGroup *RouteGroup) {
routeGroups = append(routeGroups, routeGroup)
}
func blankRoute() *RouteImpl {
return &RouteImpl{"", "", []string{}, []Runnable{}}
}
func Route(fname string, path string, args ...string) *RouteImpl {
return &RouteImpl{fname, path, args, []Runnable{}}
}

View File

@ -1,42 +1,5 @@
package main package main
type RouteImpl struct {
Name string
Path string
Vars []string
RunBefore []Runnable
}
type Runnable struct {
Contents string
Literal bool
}
func addRoute(route *RouteImpl) {
routeList = append(routeList, route)
}
func (route *RouteImpl) Before(item string, literal ...bool) *RouteImpl {
var litItem bool
if len(literal) > 0 {
litItem = literal[0]
}
route.RunBefore = append(route.RunBefore, Runnable{item, litItem})
return route
}
func addRouteGroup(routeGroup *RouteGroup) {
routeGroups = append(routeGroups, routeGroup)
}
func blankRoute() *RouteImpl {
return &RouteImpl{"", "", []string{}, []Runnable{}}
}
func Route(fname string, path string, args ...string) *RouteImpl {
return &RouteImpl{fname, path, args, []Runnable{}}
}
// TODO: How should we handle headerLite and headerVar? // TODO: How should we handle headerLite and headerVar?
func routes() { func routes() {
//addRoute("default_route","","") //addRoute("default_route","","")

View File

@ -12,7 +12,6 @@ import (
"bytes" "bytes"
"html" "html"
"io" "io"
"net"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@ -808,12 +807,8 @@ func routeLoginSubmit(w http.ResponseWriter, r *http.Request, user User) RouteEr
auth.SetCookies(w, uid, session) auth.SetCookies(w, uid, session)
if user.IsAdmin { if user.IsAdmin {
// Is this error check reundant? We already check for the error in PreRoute for the same IP // 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 {
return InternalError(err, w, r)
}
// TODO: Should we be logging this? // TODO: Should we be logging this?
log.Print("#" + strconv.Itoa(uid) + " has logged in with IP " + host) log.Printf("#%d has logged in with IP %s", uid, user.LastIP)
} }
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return nil return nil

View File

@ -270,6 +270,7 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *
} }
func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) { func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) {
user, ok := func(w http.ResponseWriter, r *http.Request) (User, bool) {
user, halt := auth.SessionCheck(w, r) user, halt := auth.SessionCheck(w, r)
if halt { if halt {
return *user, false return *user, false
@ -278,25 +279,31 @@ func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) {
return *user, true return *user, true
} }
host, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
PreError("Bad IP", w, r)
return *user, false
}
if host != user.LastIP {
_, err = stmts.updateLastIP.Exec(host, user.ID)
if err != nil {
InternalError(err, w, r)
return *user, false
}
user.LastIP = host // ! - Is this racey?
}
h := w.Header() h := w.Header()
h.Set("X-Frame-Options", "deny") h.Set("X-Frame-Options", "deny")
//h.Set("X-XSS-Protection", "1") //h.Set("X-XSS-Protection", "1")
// TODO: Set the content policy header // TODO: Set the content policy header
return *user, true return *user, true
}(w, r)
if !ok {
return user, false
}
// TODO: WIP. Refactor this to eliminate the unnecessary query
host, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
PreError("Bad IP", w, r)
return user, false
}
if host != user.LastIP {
_, err = stmts.updateLastIP.Exec(host, user.ID)
if err != nil {
InternalError(err, w, r)
return user, false
}
user.LastIP = host
}
return user, ok
} }
// SuperModeOnly makes sure that only super mods or higher can access the panel routes // SuperModeOnly makes sure that only super mods or higher can access the panel routes

View File

@ -509,48 +509,49 @@ var profile_0 = []byte(`
<img src="`) <img src="`)
var profile_1 = []byte(`" class="avatar" /> var profile_1 = []byte(`" class="avatar" />
</div> </div>
<div class="rowitem nameRow">`) <div class="rowitem nameRow">
var profile_2 = []byte(`
<span class="profileName">`) <span class="profileName">`)
var profile_3 = []byte(`</span>`) var profile_2 = []byte(`</span>`)
var profile_4 = []byte(`<span class="username" style="float: right;font-weight: normal;">`) var profile_3 = []byte(`<span class="username">`)
var profile_5 = []byte(`</span>`) var profile_4 = []byte(`</span>`)
var profile_6 = []byte(` var profile_5 = []byte(`
</div> </div>
<div class="passiveBlock">
<div class="rowitem passive"> <div class="rowitem passive">
<a class="profile_menu_item">Add Friend</a> <a class="profile_menu_item">Add Friend</a>
</div> </div>
`) `)
var profile_7 = []byte(`<div class="rowitem passive"> var profile_6 = []byte(`<div class="rowitem passive">
`) `)
var profile_8 = []byte(`<a href="/users/unban/`) var profile_7 = []byte(`<a href="/users/unban/`)
var profile_9 = []byte(`?session=`) var profile_8 = []byte(`?session=`)
var profile_10 = []byte(`" class="profile_menu_item">Unban</a> var profile_9 = []byte(`" class="profile_menu_item">Unban</a>
`) `)
var profile_11 = []byte(`<a href="#ban_user" class="profile_menu_item">Ban</a>`) var profile_10 = []byte(`<a href="#ban_user" class="profile_menu_item">Ban</a>`)
var profile_12 = []byte(` var profile_11 = []byte(`
</div>`) </div>`)
var profile_13 = []byte(` var profile_12 = []byte(`
<div class="rowitem passive"> <div class="rowitem passive">
<a href="/report/submit/`) <a href="/report/submit/`)
var profile_14 = []byte(`?session=`) var profile_13 = []byte(`?session=`)
var profile_15 = []byte(`&type=user" class="profile_menu_item report_item">Report</a> var profile_14 = []byte(`&type=user" class="profile_menu_item report_item">Report</a>
</div>
</div> </div>
</div> </div>
</div> </div>
<div id="profile_right_lane" class="colstack_right"> <div id="profile_right_lane" class="colstack_right">
`) `)
var profile_16 = []byte(` var profile_15 = []byte(`
<!-- TODO: Inline the display: none; CSS --> <!-- TODO: Inline the display: none; CSS -->
<div id="ban_user_head" class="colstack_item colstack_head hash_hide ban_user_hash" style="display: none;"> <div id="ban_user_head" class="colstack_item colstack_head hash_hide ban_user_hash" style="display: none;">
<div class="rowitem"><h1>Ban User</h1></div> <div class="rowitem"><h1>Ban User</h1></div>
</div> </div>
<form id="ban_user_form" class="hash_hide ban_user_hash" action="/users/ban/submit/`) <form id="ban_user_form" class="hash_hide ban_user_hash" action="/users/ban/submit/`)
var profile_17 = []byte(`?session=`) var profile_16 = []byte(`?session=`)
var profile_18 = []byte(`" method="post" style="display: none;"> var profile_17 = []byte(`" method="post" style="display: none;">
`) `)
var profile_19 = []byte(` var profile_18 = []byte(`
<div class="colline">If all the fields are left blank, the ban will be permanent.</div> <div class="colline">If all the fields are left blank, the ban will be permanent.</div>
<div class="colstack_item"> <div class="colstack_item">
<div class="formrow real_first_child"> <div class="formrow real_first_child">
@ -581,53 +582,53 @@ var profile_19 = []byte(`
</div> </div>
</form> </form>
`) `)
var profile_20 = []byte(` var profile_19 = []byte(`
<div id="profile_comments_head" class="colstack_item colstack_head hash_hide"> <div id="profile_comments_head" class="colstack_item colstack_head hash_hide">
<div class="rowitem"><h1>Comments</h1></div> <div class="rowitem"><h1>Comments</h1></div>
</div> </div>
<div id="profile_comments" class="colstack_item hash_hide">`) <div id="profile_comments" class="colstack_item hash_hide">`)
var profile_21 = []byte(` var profile_20 = []byte(`
<div class="rowitem passive deletable_block editable_parent simple `) <div class="rowitem passive deletable_block editable_parent simple `)
var profile_22 = []byte(`" style="`) var profile_21 = []byte(`" style="`)
var profile_23 = []byte(`background-image: url(`) var profile_22 = []byte(`background-image: url(`)
var profile_24 = []byte(`), url(/static/post-avatar-bg.jpg);background-position: 0px `) var profile_23 = []byte(`), url(/static/post-avatar-bg.jpg);background-position: 0px `)
var profile_25 = []byte(`-1`) var profile_24 = []byte(`-1`)
var profile_26 = []byte(`0px;`) var profile_25 = []byte(`0px;`)
var profile_27 = []byte(`"> var profile_26 = []byte(`">
<span class="editable_block user_content simple">`) <span class="editable_block user_content simple">`)
var profile_28 = []byte(`</span> var profile_27 = []byte(`</span>
<span class="controls"> <span class="controls">
<a href="`) <a href="`)
var profile_29 = []byte(`" class="real_username username">`) var profile_28 = []byte(`" class="real_username username">`)
var profile_30 = []byte(`</a>&nbsp;&nbsp; var profile_29 = []byte(`</a>&nbsp;&nbsp;
`) `)
var profile_31 = []byte(`<a href="/profile/reply/edit/submit/`) var profile_30 = []byte(`<a href="/profile/reply/edit/submit/`)
var profile_32 = []byte(`" class="mod_button" title="Edit Item"><button class="username edit_item edit_label"></button></a> var profile_31 = []byte(`" class="mod_button" title="Edit Item"><button class="username edit_item edit_label"></button></a>
<a href="/profile/reply/delete/submit/`) <a href="/profile/reply/delete/submit/`)
var profile_33 = []byte(`" class="mod_button" title="Delete Item"><button class="username delete_item trash_label"></button></a>`) var profile_32 = []byte(`" class="mod_button" title="Delete Item"><button class="username delete_item trash_label"></button></a>`)
var profile_34 = []byte(` var profile_33 = []byte(`
<a class="mod_button" href="/report/submit/`) <a class="mod_button" href="/report/submit/`)
var profile_35 = []byte(`?session=`) var profile_34 = []byte(`?session=`)
var profile_36 = []byte(`&type=user-reply"><button class="username report_item flag_label"></button></a> var profile_35 = []byte(`&type=user-reply"><button class="username report_item flag_label"></button></a>
`) `)
var profile_37 = []byte(`<a class="username hide_on_mobile user_tag" style="float: right;">`) var profile_36 = []byte(`<a class="username hide_on_mobile user_tag" style="float: right;">`)
var profile_38 = []byte(`</a>`) var profile_37 = []byte(`</a>`)
var profile_39 = []byte(` var profile_38 = []byte(`
</span> </span>
</div> </div>
`) `)
var profile_40 = []byte(`</div> var profile_39 = []byte(`</div>
`) `)
var profile_41 = []byte(` var profile_40 = []byte(`
<form id="profile_comments_form" class="hash_hide" action="/profile/reply/create/" method="post"> <form id="profile_comments_form" class="hash_hide" action="/profile/reply/create/" method="post">
<input name="uid" value='`) <input name="uid" value='`)
var profile_42 = []byte(`' type="hidden" /> var profile_41 = []byte(`' type="hidden" />
<div class="colstack_item topic_reply_form" style="border-top: none;"> <div class="colstack_item topic_reply_form" style="border-top: none;">
<div class="formrow"> <div class="formrow">
<div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div> <div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div>
@ -638,13 +639,13 @@ var profile_42 = []byte(`' type="hidden" />
</div> </div>
</form> </form>
`) `)
var profile_43 = []byte(` var profile_42 = []byte(`
</div> </div>
</div> </div>
`) `)
var profile_44 = []byte(` var profile_43 = []byte(`
<script type="text/javascript"> <script type="text/javascript">
function handle_profile_hashbit() { function handle_profile_hashbit() {
var hash_class = "" var hash_class = ""

View File

@ -77,91 +77,90 @@ w.Write(header_18)
w.Write(profile_0) w.Write(profile_0)
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Avatar)) w.Write([]byte(tmpl_profile_vars.ProfileOwner.Avatar))
w.Write(profile_1) w.Write(profile_1)
w.Write(profile_2)
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Name)) w.Write([]byte(tmpl_profile_vars.ProfileOwner.Name))
w.Write(profile_3) w.Write(profile_2)
if tmpl_profile_vars.ProfileOwner.Tag != "" { if tmpl_profile_vars.ProfileOwner.Tag != "" {
w.Write(profile_4) w.Write(profile_3)
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Tag)) w.Write([]byte(tmpl_profile_vars.ProfileOwner.Tag))
w.Write(profile_5) w.Write(profile_4)
} }
w.Write(profile_6) w.Write(profile_5)
if tmpl_profile_vars.CurrentUser.IsSuperMod && !tmpl_profile_vars.ProfileOwner.IsSuperMod { if tmpl_profile_vars.CurrentUser.IsSuperMod && !tmpl_profile_vars.ProfileOwner.IsSuperMod {
w.Write(profile_7) w.Write(profile_6)
if tmpl_profile_vars.ProfileOwner.IsBanned { if tmpl_profile_vars.ProfileOwner.IsBanned {
w.Write(profile_8) w.Write(profile_7)
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
w.Write(profile_9) w.Write(profile_8)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(profile_10) w.Write(profile_9)
} else { } else {
w.Write(profile_10)
}
w.Write(profile_11) w.Write(profile_11)
} }
w.Write(profile_12) w.Write(profile_12)
} w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
w.Write(profile_13) w.Write(profile_13)
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(profile_14) w.Write(profile_14)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(profile_15)
if tmpl_profile_vars.CurrentUser.Perms.BanUsers { if tmpl_profile_vars.CurrentUser.Perms.BanUsers {
w.Write(profile_16) w.Write(profile_15)
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
w.Write(profile_17) w.Write(profile_16)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(profile_17)
w.Write(profile_18) w.Write(profile_18)
w.Write(profile_19)
} }
w.Write(profile_20) w.Write(profile_19)
if len(tmpl_profile_vars.ItemList) != 0 { if len(tmpl_profile_vars.ItemList) != 0 {
for _, item := range tmpl_profile_vars.ItemList { for _, item := range tmpl_profile_vars.ItemList {
w.Write(profile_21) w.Write(profile_20)
w.Write([]byte(item.ClassName)) w.Write([]byte(item.ClassName))
w.Write(profile_22) w.Write(profile_21)
if item.Avatar != "" { if item.Avatar != "" {
w.Write(profile_23) w.Write(profile_22)
w.Write([]byte(item.Avatar)) w.Write([]byte(item.Avatar))
w.Write(profile_24) w.Write(profile_23)
if item.ContentLines <= 5 { if item.ContentLines <= 5 {
w.Write(profile_24)
}
w.Write(profile_25) w.Write(profile_25)
} }
w.Write(profile_26) w.Write(profile_26)
}
w.Write(profile_27)
w.Write([]byte(item.ContentHtml)) w.Write([]byte(item.ContentHtml))
w.Write(profile_28) w.Write(profile_27)
w.Write([]byte(item.UserLink)) w.Write([]byte(item.UserLink))
w.Write(profile_29) w.Write(profile_28)
w.Write([]byte(item.CreatedByName)) w.Write([]byte(item.CreatedByName))
w.Write(profile_30) w.Write(profile_29)
if tmpl_profile_vars.CurrentUser.IsMod { if tmpl_profile_vars.CurrentUser.IsMod {
w.Write(profile_30)
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_31) w.Write(profile_31)
w.Write([]byte(strconv.Itoa(item.ID))) w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_32) w.Write(profile_32)
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_33)
} }
w.Write(profile_34) w.Write(profile_33)
w.Write([]byte(strconv.Itoa(item.ID))) w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_35) w.Write(profile_34)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(profile_36) w.Write(profile_35)
if item.Tag != "" { if item.Tag != "" {
w.Write(profile_37) w.Write(profile_36)
w.Write([]byte(item.Tag)) w.Write([]byte(item.Tag))
w.Write(profile_37)
}
w.Write(profile_38) w.Write(profile_38)
} }
}
w.Write(profile_39) w.Write(profile_39)
}
}
w.Write(profile_40)
if !tmpl_profile_vars.CurrentUser.IsBanned { if !tmpl_profile_vars.CurrentUser.IsBanned {
w.Write(profile_41) w.Write(profile_40)
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID))) w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
w.Write(profile_42) w.Write(profile_41)
} }
w.Write(profile_42)
w.Write(profile_43) w.Write(profile_43)
w.Write(profile_44)
w.Write(footer_0) w.Write(footer_0)
if len(tmpl_profile_vars.Header.Themes) != 0 { if len(tmpl_profile_vars.Header.Themes) != 0 {
for _, item := range tmpl_profile_vars.Header.Themes { for _, item := range tmpl_profile_vars.Header.Themes {

View File

@ -10,9 +10,10 @@
<div class="rowitem avatarRow"> <div class="rowitem avatarRow">
<img src="{{.ProfileOwner.Avatar}}" class="avatar" /> <img src="{{.ProfileOwner.Avatar}}" class="avatar" />
</div> </div>
<div class="rowitem nameRow">{{/** TODO: Stop inlining this CSS **/}} <div class="rowitem nameRow">
<span class="profileName">{{.ProfileOwner.Name}}</span>{{if .ProfileOwner.Tag}}<span class="username" style="float: right;font-weight: normal;">{{.ProfileOwner.Tag}}</span>{{end}} <span class="profileName">{{.ProfileOwner.Name}}</span>{{if .ProfileOwner.Tag}}<span class="username">{{.ProfileOwner.Tag}}</span>{{end}}
</div> </div>
<div class="passiveBlock">
<div class="rowitem passive"> <div class="rowitem passive">
<a class="profile_menu_item">Add Friend</a> <a class="profile_menu_item">Add Friend</a>
</div> </div>
@ -24,6 +25,7 @@
<a href="/report/submit/{{.ProfileOwner.ID}}?session={{.CurrentUser.Session}}&type=user" class="profile_menu_item report_item">Report</a> <a href="/report/submit/{{.ProfileOwner.ID}}?session={{.CurrentUser.Session}}&type=user" class="profile_menu_item report_item">Report</a>
</div> </div>
</div> </div>
</div>
</div> </div>
<div id="profile_right_lane" class="colstack_right"> <div id="profile_right_lane" class="colstack_right">

View File

@ -714,6 +714,7 @@ select, input, textarea {
} }
#profile_left_pane .avatarRow { #profile_left_pane .avatarRow {
padding: 24px; padding: 24px;
padding-bottom: 8px;
} }
#profile_left_pane .avatar { #profile_left_pane .avatar {
border-radius: 80px; border-radius: 80px;
@ -724,6 +725,12 @@ select, input, textarea {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
#profile_left_pane .nameRow .username {
text-align: center;
}
#profile_left_pane .profileName {
font-size: 19px;
}
#profile_right_lane { #profile_right_lane {
width: 100%; width: 100%;
margin-right: 12px; margin-right: 12px;

View File

@ -667,6 +667,10 @@ input, select, textarea {
display: block; display: block;
margin-top: 3px; margin-top: 3px;
} }
#profile_left_pane .nameRow .username {
float: right;
font-weight: normal;
}
#profile_left_lane .profileName { #profile_left_lane .profileName {
font-size: 18px; font-size: 18px;
} }

View File

@ -710,6 +710,10 @@ button.username {
margin: 0; margin: 0;
display: block; display: block;
} }
#profile_left_pane .nameRow .username {
float: right;
font-weight: normal;
}
#profile_right_lane { #profile_right_lane {
width: calc(100% - 230px); width: calc(100% - 230px);
} }

View File

@ -546,6 +546,10 @@ button.username {
#profile_left_lane .avatarRow { #profile_left_lane .avatarRow {
padding: 0; padding: 0;
} }
#profile_left_pane .nameRow .username {
float: right;
font-weight: normal;
}
/* Media Queries */ /* Media Queries */

View File

@ -767,6 +767,10 @@ button.username {
display: block; display: block;
margin-top: 3px; margin-top: 3px;
} }
#profile_left_pane .nameRow .username {
float: right;
font-weight: normal;
}
#profile_left_lane .profileName { #profile_left_lane .profileName {
font-size: 18px; font-size: 18px;
} }

View File

@ -24,3 +24,6 @@ go get -u github.com/robertkrimen/otto
echo "Updating the Riot Search Engine" echo "Updating the Riot Search Engine"
go get -u github.com/go-ego/riot go get -u github.com/go-ego/riot
echo "Updating the Rez Image Resizer"
go get -u github.com/bamiaux/rez

View File

@ -68,12 +68,19 @@ if %errorlevel% neq 0 (
exit /b %errorlevel% exit /b %errorlevel%
) )
echo Installing the Riot Search Engine echo Updating the Riot Search Engine
go get -u github.com/go-ego/riot go get -u github.com/go-ego/riot
if %errorlevel% neq 0 ( if %errorlevel% neq 0 (
pause pause
exit /b %errorlevel% exit /b %errorlevel%
) )
echo Updating the Rez Image Resizer
go get -u github.com/bamiaux/rez
if %errorlevel% neq 0 (
pause
exit /b %errorlevel%
)
echo The dependencies were successfully updated echo The dependencies were successfully updated
pause pause

View File

@ -54,7 +54,7 @@ type User struct {
Tag string Tag string
Level int Level int
Score int Score int
LastIP string LastIP string // ! This part of the UserCache data might fall out of date
TempGroup int TempGroup int
} }