Added support for polls, minus the results UI, we're planning to have a nice little chart for this.
Refactored the request logging logic into it's own function.
This commit is contained in:
parent
ed57052092
commit
9efed8c0bc
@ -11,6 +11,8 @@ var Polls PollStore
|
||||
|
||||
type Poll struct {
|
||||
ID int
|
||||
ParentID int
|
||||
ParentTable string
|
||||
Type int // 0: Single choice, 1: Multiple choice, 2: Multiple choice w/ points
|
||||
//AntiCheat bool // Apply various mitigations for cheating
|
||||
// GroupPower map[gid]points // The number of points a group can spend in this poll, defaults to 1
|
||||
@ -21,6 +23,10 @@ type Poll struct {
|
||||
VoteCount int
|
||||
}
|
||||
|
||||
func (poll *Poll) CastVote(optionIndex int, uid int, ipaddress string) error {
|
||||
return Polls.CastVote(optionIndex, poll.ID, uid, ipaddress) // TODO: Move the query into a pollStmts rather than having it in the store
|
||||
}
|
||||
|
||||
func (poll *Poll) Copy() Poll {
|
||||
return *poll
|
||||
}
|
||||
@ -31,6 +37,8 @@ type PollOption struct {
|
||||
}
|
||||
|
||||
type Pollable interface {
|
||||
GetID() int
|
||||
GetTable() string
|
||||
SetPoll(pollID int) error
|
||||
}
|
||||
|
||||
@ -38,6 +46,7 @@ type PollStore interface {
|
||||
Get(id int) (*Poll, error)
|
||||
Exists(id int) bool
|
||||
Create(parent Pollable, pollType int, pollOptions map[int]string) (int, error)
|
||||
CastVote(optionIndex int, pollID int, uid int, ipaddress string) error
|
||||
Reload(id int) error
|
||||
//GlobalCount() int
|
||||
|
||||
@ -51,6 +60,8 @@ type DefaultPollStore struct {
|
||||
get *sql.Stmt
|
||||
exists *sql.Stmt
|
||||
create *sql.Stmt
|
||||
addVote *sql.Stmt
|
||||
incrementVoteCount *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
//pollCount *sql.Stmt
|
||||
}
|
||||
@ -63,9 +74,11 @@ func NewDefaultPollStore(cache PollCache) (*DefaultPollStore, error) {
|
||||
// TODO: Add an admin version of registerStmt with more flexibility?
|
||||
return &DefaultPollStore{
|
||||
cache: cache,
|
||||
get: acc.Select("polls").Columns("type, options, votes").Where("pollID = ?").Prepare(),
|
||||
get: acc.Select("polls").Columns("parentID, parentTable, type, options, votes").Where("pollID = ?").Prepare(),
|
||||
exists: acc.Select("polls").Columns("pollID").Where("pollID = ?").Prepare(),
|
||||
create: acc.Insert("polls").Columns("type, options").Fields("?,?").Prepare(),
|
||||
create: acc.Insert("polls").Columns("parentID, parentTable, type, options").Fields("?,?,?,?").Prepare(),
|
||||
addVote: acc.Insert("polls_votes").Columns("pollID, uid, option, castAt, ipaddress").Fields("?,?,?,UTC_TIMESTAMP(),?").Prepare(),
|
||||
incrementVoteCount: acc.Update("polls").Set("votes = votes + 1").Where("pollID = ?").Prepare(),
|
||||
//pollCount: acc.SimpleCount("polls", "", ""),
|
||||
}, acc.FirstError()
|
||||
}
|
||||
@ -86,7 +99,7 @@ func (store *DefaultPollStore) Get(id int) (*Poll, error) {
|
||||
|
||||
poll = &Poll{ID: id}
|
||||
var optionTxt []byte
|
||||
err = store.get.QueryRow(id).Scan(&poll.Type, &optionTxt, &poll.VoteCount)
|
||||
err = store.get.QueryRow(id).Scan(&poll.ParentID, &poll.ParentTable, &poll.Type, &optionTxt, &poll.VoteCount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -102,7 +115,7 @@ func (store *DefaultPollStore) Get(id int) (*Poll, error) {
|
||||
func (store *DefaultPollStore) Reload(id int) error {
|
||||
poll := &Poll{ID: id}
|
||||
var optionTxt []byte
|
||||
err := store.get.QueryRow(id).Scan(&poll.Type, &optionTxt, &poll.VoteCount)
|
||||
err := store.get.QueryRow(id).Scan(&poll.ParentID, &poll.ParentTable, &poll.Type, &optionTxt, &poll.VoteCount)
|
||||
if err != nil {
|
||||
store.cache.Remove(id)
|
||||
return err
|
||||
@ -127,13 +140,23 @@ func (store *DefaultPollStore) unpackOptionsMap(rawOptions map[int]string) []Pol
|
||||
return options
|
||||
}
|
||||
|
||||
// TODO: Use a transaction for this?
|
||||
func (store *DefaultPollStore) CastVote(optionIndex int, pollID int, uid int, ipaddress string) error {
|
||||
_, err := store.addVote.Exec(pollID, uid, optionIndex, ipaddress)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = store.incrementVoteCount.Exec(pollID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (store *DefaultPollStore) Create(parent Pollable, pollType int, pollOptions map[int]string) (id int, err error) {
|
||||
pollOptionsTxt, err := json.Marshal(pollOptions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
res, err := store.create.Exec(pollType, pollOptionsTxt) //pollOptionsTxt
|
||||
res, err := store.create.Exec(parent.GetID(), parent.GetTable(), pollType, pollOptionsTxt)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -263,6 +263,7 @@ func (topic *Topic) Update(name string, content string) error {
|
||||
|
||||
func (topic *Topic) SetPoll(pollID int) error {
|
||||
_, err := topicStmts.setPoll.Exec(pollID, topic.ID) // TODO: Sniff if this changed anything to see if we hit an existing poll
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
@ -278,6 +279,13 @@ func (topic *Topic) CreateActionReply(action string, ipaddress string, user User
|
||||
return err
|
||||
}
|
||||
|
||||
func (topic *Topic) GetID() int {
|
||||
return topic.ID
|
||||
}
|
||||
func (topic *Topic) GetTable() string {
|
||||
return "topics"
|
||||
}
|
||||
|
||||
// Copy gives you a non-pointer concurrency safe copy of the topic
|
||||
func (topic *Topic) Copy() Topic {
|
||||
return *topic
|
||||
|
164
gen_router.go
164
gen_router.go
@ -100,6 +100,7 @@ var RouteMap = map[string]interface{}{
|
||||
"routeProfileReplyCreateSubmit": routeProfileReplyCreateSubmit,
|
||||
"routes.ProfileReplyEditSubmit": routes.ProfileReplyEditSubmit,
|
||||
"routes.ProfileReplyDeleteSubmit": routes.ProfileReplyDeleteSubmit,
|
||||
"routes.PollVote": routes.PollVote,
|
||||
"routeLogin": routeLogin,
|
||||
"routeRegister": routeRegister,
|
||||
"routeLogout": routeLogout,
|
||||
@ -196,14 +197,15 @@ var routeMapEnum = map[string]int{
|
||||
"routeProfileReplyCreateSubmit": 81,
|
||||
"routes.ProfileReplyEditSubmit": 82,
|
||||
"routes.ProfileReplyDeleteSubmit": 83,
|
||||
"routeLogin": 84,
|
||||
"routeRegister": 85,
|
||||
"routeLogout": 86,
|
||||
"routeLoginSubmit": 87,
|
||||
"routeRegisterSubmit": 88,
|
||||
"routeDynamic": 89,
|
||||
"routeUploads": 90,
|
||||
"BadRoute": 91,
|
||||
"routes.PollVote": 84,
|
||||
"routeLogin": 85,
|
||||
"routeRegister": 86,
|
||||
"routeLogout": 87,
|
||||
"routeLoginSubmit": 88,
|
||||
"routeRegisterSubmit": 89,
|
||||
"routeDynamic": 90,
|
||||
"routeUploads": 91,
|
||||
"BadRoute": 92,
|
||||
}
|
||||
var reverseRouteMapEnum = map[int]string{
|
||||
0: "routeAPI",
|
||||
@ -290,14 +292,15 @@ var reverseRouteMapEnum = map[int]string{
|
||||
81: "routeProfileReplyCreateSubmit",
|
||||
82: "routes.ProfileReplyEditSubmit",
|
||||
83: "routes.ProfileReplyDeleteSubmit",
|
||||
84: "routeLogin",
|
||||
85: "routeRegister",
|
||||
86: "routeLogout",
|
||||
87: "routeLoginSubmit",
|
||||
88: "routeRegisterSubmit",
|
||||
89: "routeDynamic",
|
||||
90: "routeUploads",
|
||||
91: "BadRoute",
|
||||
84: "routes.PollVote",
|
||||
85: "routeLogin",
|
||||
86: "routeRegister",
|
||||
87: "routeLogout",
|
||||
88: "routeLoginSubmit",
|
||||
89: "routeRegisterSubmit",
|
||||
90: "routeDynamic",
|
||||
91: "routeUploads",
|
||||
92: "BadRoute",
|
||||
}
|
||||
var agentMapEnum = map[string]int{
|
||||
"unknown": 0,
|
||||
@ -396,15 +399,7 @@ func (router *GenRouter) RemoveFunc(pattern string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Pass the default route or config struct to the router rather than accessing it via a package global
|
||||
// TODO: SetDefaultRoute
|
||||
// TODO: GetDefaultRoute
|
||||
|
||||
func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
if len(req.URL.Path) == 0 || req.URL.Path[0] != '/' || req.Host != common.Site.Host {
|
||||
w.WriteHeader(200) // 405
|
||||
w.Write([]byte(""))
|
||||
log.Print("Malformed Request")
|
||||
func (router *GenRouter) DumpRequest(req *http.Request) {
|
||||
log.Print("UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
for key, value := range req.Header {
|
||||
@ -417,6 +412,23 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
}
|
||||
|
||||
func (router *GenRouter) SuspiciousRequest(req *http.Request) {
|
||||
log.Print("Supicious Request")
|
||||
router.DumpRequest(req)
|
||||
common.AgentViewCounter.Bump(18)
|
||||
}
|
||||
|
||||
// TODO: Pass the default route or config struct to the router rather than accessing it via a package global
|
||||
// TODO: SetDefaultRoute
|
||||
// TODO: GetDefaultRoute
|
||||
func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
if len(req.URL.Path) == 0 || req.URL.Path[0] != '/' || req.Host != common.Site.Host {
|
||||
w.WriteHeader(200) // 400
|
||||
w.Write([]byte(""))
|
||||
log.Print("Malformed Request")
|
||||
router.DumpRequest(req)
|
||||
common.AgentViewCounter.Bump(17)
|
||||
return
|
||||
}
|
||||
@ -425,37 +437,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
// TODO: Cover more suspicious strings and at a lower layer than this
|
||||
for _, char := range req.URL.Path {
|
||||
if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) {
|
||||
log.Print("Suspicious UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
for key, value := range req.Header {
|
||||
for _, vvalue := range value {
|
||||
log.Print("Header '" + key + "': " + vvalue + "!!")
|
||||
}
|
||||
}
|
||||
log.Print("req.Host: ", req.Host)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
common.AgentViewCounter.Bump(18)
|
||||
router.SuspiciousRequest(req)
|
||||
break
|
||||
}
|
||||
}
|
||||
lowerPath := strings.ToLower(req.URL.Path)
|
||||
// TODO: Flag any requests which has a dot with anything but a number after that
|
||||
if strings.Contains(req.URL.Path,"..") || strings.Contains(req.URL.Path,"--") || strings.Contains(req.URL.Path,".php") || strings.Contains(req.URL.Path,".asp") || strings.Contains(req.URL.Path,".cgi") {
|
||||
log.Print("Suspicious UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
for key, value := range req.Header {
|
||||
for _, vvalue := range value {
|
||||
log.Print("Header '" + key + "': " + vvalue + "!!")
|
||||
}
|
||||
}
|
||||
log.Print("req.Host: ", req.Host)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
common.AgentViewCounter.Bump(18)
|
||||
if strings.Contains(req.URL.Path,"..") || strings.Contains(req.URL.Path,"--") || strings.Contains(lowerPath,".php") || strings.Contains(lowerPath,".asp") || strings.Contains(lowerPath,".cgi") || strings.Contains(lowerPath,".py") || strings.Contains(lowerPath,".sql") {
|
||||
router.SuspiciousRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
@ -534,38 +523,13 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
common.AgentViewCounter.Bump(16)
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Blank UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
|
||||
for key, value := range req.Header {
|
||||
for _, vvalue := range value {
|
||||
log.Print("Header '" + key + "': " + vvalue + "!!")
|
||||
}
|
||||
}
|
||||
log.Print("prefix: ", prefix)
|
||||
log.Print("req.Host: ", req.Host)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("extraData: ", extraData)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
router.DumpRequest(req)
|
||||
}
|
||||
default:
|
||||
common.AgentViewCounter.Bump(0)
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Unknown UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
for key, value := range req.Header {
|
||||
for _, vvalue := range value {
|
||||
log.Print("Header '" + key + "': " + vvalue + "!!")
|
||||
}
|
||||
}
|
||||
log.Print("prefix: ", prefix)
|
||||
log.Print("req.Host: ", req.Host)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("extraData: ", extraData)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
router.DumpRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1422,13 +1386,34 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
}
|
||||
case "/poll":
|
||||
switch(req.URL.Path) {
|
||||
case "/poll/vote/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
}
|
||||
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(84)
|
||||
err = routes.PollVote(w,req,user,extraData)
|
||||
}
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
}
|
||||
case "/accounts":
|
||||
switch(req.URL.Path) {
|
||||
case "/accounts/login/":
|
||||
common.RouteViewCounter.Bump(84)
|
||||
common.RouteViewCounter.Bump(85)
|
||||
err = routeLogin(w,req,user)
|
||||
case "/accounts/create/":
|
||||
common.RouteViewCounter.Bump(85)
|
||||
common.RouteViewCounter.Bump(86)
|
||||
err = routeRegister(w,req,user)
|
||||
case "/accounts/logout/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
@ -1443,7 +1428,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(86)
|
||||
common.RouteViewCounter.Bump(87)
|
||||
err = routeLogout(w,req,user)
|
||||
case "/accounts/login/submit/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
@ -1452,7 +1437,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(87)
|
||||
common.RouteViewCounter.Bump(88)
|
||||
err = routeLoginSubmit(w,req,user)
|
||||
case "/accounts/create/submit/":
|
||||
err = common.ParseForm(w,req,user)
|
||||
@ -1461,7 +1446,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(88)
|
||||
common.RouteViewCounter.Bump(89)
|
||||
err = routeRegisterSubmit(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
@ -1478,7 +1463,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
common.NotFound(w,req)
|
||||
return
|
||||
}
|
||||
common.RouteViewCounter.Bump(90)
|
||||
common.RouteViewCounter.Bump(91)
|
||||
req.URL.Path += extraData
|
||||
// TODO: Find a way to propagate errors up from this?
|
||||
router.UploadHandler(w,req) // TODO: Count these views
|
||||
@ -1499,7 +1484,6 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
return*/
|
||||
}
|
||||
|
||||
if extraData != "" {
|
||||
common.NotFound(w,req)
|
||||
return
|
||||
@ -1522,7 +1506,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
router.RUnlock()
|
||||
|
||||
if ok {
|
||||
common.RouteViewCounter.Bump(89) // TODO: Be more specific about *which* dynamic route it is
|
||||
common.RouteViewCounter.Bump(90) // TODO: Be more specific about *which* dynamic route it is
|
||||
req.URL.Path += extraData
|
||||
err = handle(w,req,user)
|
||||
if err != nil {
|
||||
@ -1531,7 +1515,11 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
common.RouteViewCounter.Bump(91)
|
||||
lowerPath := strings.ToLower(req.URL.Path)
|
||||
if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") {
|
||||
router.SuspiciousRequest(req)
|
||||
}
|
||||
common.RouteViewCounter.Bump(92)
|
||||
common.NotFound(w,req)
|
||||
}
|
||||
}
|
||||
|
@ -221,6 +221,8 @@ func createTables(adapter qgen.Adapter) error {
|
||||
qgen.Install.CreateTable("polls", "utf8mb4", "utf8mb4_general_ci",
|
||||
[]qgen.DBTableColumn{
|
||||
qgen.DBTableColumn{"pollID", "int", 0, false, true, ""},
|
||||
qgen.DBTableColumn{"parentID", "int", 0, false, false, "0"},
|
||||
qgen.DBTableColumn{"parentTable", "varchar", 100, false, false, "topics"}, // topics, replies
|
||||
qgen.DBTableColumn{"type", "int", 0, false, false, "0"},
|
||||
qgen.DBTableColumn{"options", "json", 0, false, false, ""},
|
||||
qgen.DBTableColumn{"votes", "int", 0, false, false, "0"},
|
||||
|
@ -275,15 +275,7 @@ func (router *GenRouter) RemoveFunc(pattern string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Pass the default route or config struct to the router rather than accessing it via a package global
|
||||
// TODO: SetDefaultRoute
|
||||
// TODO: GetDefaultRoute
|
||||
|
||||
func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
if len(req.URL.Path) == 0 || req.URL.Path[0] != '/' || req.Host != common.Site.Host {
|
||||
w.WriteHeader(200) // 405
|
||||
w.Write([]byte(""))
|
||||
log.Print("Malformed Request")
|
||||
func (router *GenRouter) DumpRequest(req *http.Request) {
|
||||
log.Print("UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
for key, value := range req.Header {
|
||||
@ -296,6 +288,23 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
}
|
||||
|
||||
func (router *GenRouter) SuspiciousRequest(req *http.Request) {
|
||||
log.Print("Supicious Request")
|
||||
router.DumpRequest(req)
|
||||
common.AgentViewCounter.Bump({{.AllAgentMap.suspicious}})
|
||||
}
|
||||
|
||||
// TODO: Pass the default route or config struct to the router rather than accessing it via a package global
|
||||
// TODO: SetDefaultRoute
|
||||
// TODO: GetDefaultRoute
|
||||
func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
if len(req.URL.Path) == 0 || req.URL.Path[0] != '/' || req.Host != common.Site.Host {
|
||||
w.WriteHeader(200) // 400
|
||||
w.Write([]byte(""))
|
||||
log.Print("Malformed Request")
|
||||
router.DumpRequest(req)
|
||||
common.AgentViewCounter.Bump({{.AllAgentMap.malformed}})
|
||||
return
|
||||
}
|
||||
@ -304,37 +313,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
// TODO: Cover more suspicious strings and at a lower layer than this
|
||||
for _, char := range req.URL.Path {
|
||||
if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) {
|
||||
log.Print("Suspicious UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
for key, value := range req.Header {
|
||||
for _, vvalue := range value {
|
||||
log.Print("Header '" + key + "': " + vvalue + "!!")
|
||||
}
|
||||
}
|
||||
log.Print("req.Host: ", req.Host)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
common.AgentViewCounter.Bump({{.AllAgentMap.suspicious}})
|
||||
router.SuspiciousRequest(req)
|
||||
break
|
||||
}
|
||||
}
|
||||
lowerPath := strings.ToLower(req.URL.Path)
|
||||
// TODO: Flag any requests which has a dot with anything but a number after that
|
||||
if strings.Contains(req.URL.Path,"..") || strings.Contains(req.URL.Path,"--") || strings.Contains(req.URL.Path,".php") || strings.Contains(req.URL.Path,".asp") || strings.Contains(req.URL.Path,".cgi") {
|
||||
log.Print("Suspicious UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
for key, value := range req.Header {
|
||||
for _, vvalue := range value {
|
||||
log.Print("Header '" + key + "': " + vvalue + "!!")
|
||||
}
|
||||
}
|
||||
log.Print("req.Host: ", req.Host)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
common.AgentViewCounter.Bump({{.AllAgentMap.suspicious}})
|
||||
if strings.Contains(req.URL.Path,"..") || strings.Contains(req.URL.Path,"--") || strings.Contains(lowerPath,".php") || strings.Contains(lowerPath,".asp") || strings.Contains(lowerPath,".cgi") || strings.Contains(lowerPath,".py") || strings.Contains(lowerPath,".sql") {
|
||||
router.SuspiciousRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
@ -413,38 +399,13 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
common.AgentViewCounter.Bump({{.AllAgentMap.blank}})
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Blank UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
|
||||
for key, value := range req.Header {
|
||||
for _, vvalue := range value {
|
||||
log.Print("Header '" + key + "': " + vvalue + "!!")
|
||||
}
|
||||
}
|
||||
log.Print("prefix: ", prefix)
|
||||
log.Print("req.Host: ", req.Host)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("extraData: ", extraData)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
router.DumpRequest(req)
|
||||
}
|
||||
default:
|
||||
common.AgentViewCounter.Bump({{.AllAgentMap.unknown}})
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Unknown UA: ", req.UserAgent())
|
||||
log.Print("Method: ", req.Method)
|
||||
for key, value := range req.Header {
|
||||
for _, vvalue := range value {
|
||||
log.Print("Header '" + key + "': " + vvalue + "!!")
|
||||
}
|
||||
}
|
||||
log.Print("prefix: ", prefix)
|
||||
log.Print("req.Host: ", req.Host)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
log.Print("req.URL.RawQuery: ", req.URL.RawQuery)
|
||||
log.Print("extraData: ", extraData)
|
||||
log.Print("req.Referer(): ", req.Referer())
|
||||
log.Print("req.RemoteAddr: ", req.RemoteAddr)
|
||||
router.DumpRequest(req)
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,7 +453,6 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
return*/
|
||||
}
|
||||
|
||||
if extraData != "" {
|
||||
common.NotFound(w,req)
|
||||
return
|
||||
@ -524,6 +484,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
lowerPath := strings.ToLower(req.URL.Path)
|
||||
if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") {
|
||||
router.SuspiciousRequest(req)
|
||||
}
|
||||
common.RouteViewCounter.Bump({{.AllRouteMap.BadRoute}})
|
||||
common.NotFound(w,req)
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ func routes() {
|
||||
buildTopicRoutes()
|
||||
buildReplyRoutes()
|
||||
buildProfileReplyRoutes()
|
||||
buildPollRoutes()
|
||||
buildAccountRoutes()
|
||||
|
||||
addRoute(Special("routeWebsockets", "/ws/"))
|
||||
@ -104,6 +105,14 @@ func buildProfileReplyRoutes() {
|
||||
addRouteGroup(pReplyGroup)
|
||||
}
|
||||
|
||||
func buildPollRoutes() {
|
||||
pollGroup := newRouteGroup("/poll/")
|
||||
pollGroup.Routes(
|
||||
Action("routes.PollVote", "/poll/vote/", "extraData"),
|
||||
)
|
||||
addRouteGroup(pollGroup)
|
||||
}
|
||||
|
||||
func buildAccountRoutes() {
|
||||
//router.HandleFunc("/accounts/list/", routeLogin) // Redirect /accounts/ and /user/ to here.. // Get a list of all of the accounts on the forum
|
||||
accReplyGroup := newRouteGroup("/accounts/")
|
||||
|
67
routes/poll.go
Normal file
67
routes/poll.go
Normal file
@ -0,0 +1,67 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"../common"
|
||||
)
|
||||
|
||||
func PollVote(w http.ResponseWriter, r *http.Request, user common.User, sPollID string) common.RouteError {
|
||||
pollID, err := strconv.Atoi(sPollID)
|
||||
if err != nil {
|
||||
return common.PreError("The provided PollID is not a valid number.", w, r)
|
||||
}
|
||||
|
||||
poll, err := common.Polls.Get(pollID)
|
||||
if err == sql.ErrNoRows {
|
||||
return common.PreError("The poll you tried to vote for doesn't exist.", w, r)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
var topic *common.Topic
|
||||
if poll.ParentTable == "replies" {
|
||||
reply, err := common.Rstore.Get(poll.ParentID)
|
||||
if err == sql.ErrNoRows {
|
||||
return common.PreError("The parent post doesn't exist.", w, r)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
topic, err = common.Topics.Get(reply.ParentID)
|
||||
} else if poll.ParentTable == "topics" {
|
||||
topic, err = common.Topics.Get(poll.ParentID)
|
||||
} else {
|
||||
return common.InternalError(errors.New("Unknown parentTable for poll"), w, r)
|
||||
}
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
return common.PreError("The parent topic doesn't exist.", w, r)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
optionIndex, err := strconv.Atoi(r.PostFormValue("poll_option_input"))
|
||||
if err != nil {
|
||||
return common.LocalError("Malformed input", w, r, user)
|
||||
}
|
||||
|
||||
err = poll.CastVote(optionIndex, user.ID, user.LastIP)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(topic.ID), http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
@ -144,7 +144,6 @@ func CreateTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
||||
if r.PostFormValue("has_poll") == "1" {
|
||||
var maxPollOptions = 10
|
||||
var pollInputItems = make(map[int]string)
|
||||
var pollInputCount = 0
|
||||
for key, values := range r.Form {
|
||||
//if common.Dev.SuperDebug {
|
||||
log.Print("key: ", key)
|
||||
@ -165,8 +164,7 @@ func CreateTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
||||
|
||||
// If there are duplicates, then something has gone horribly wrong, so let's ignore them, this'll likely happen during an attack
|
||||
_, exists := pollInputItems[index]
|
||||
if !exists {
|
||||
pollInputCount++
|
||||
if !exists && len(html.EscapeString(value)) != 0 {
|
||||
pollInputItems[index] = html.EscapeString(value)
|
||||
|
||||
if len(pollInputItems) >= maxPollOptions {
|
||||
@ -177,8 +175,14 @@ func CreateTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the indices are sequential to avoid out of bounds issues
|
||||
var seqPollInputItems = make(map[int]string)
|
||||
for i := 0; i < len(pollInputItems); i++ {
|
||||
seqPollInputItems[i] = pollInputItems[i]
|
||||
}
|
||||
|
||||
pollType := 0 // Basic single choice
|
||||
_, err := common.Polls.Create(topic, pollType, pollInputItems)
|
||||
_, err := common.Polls.Create(topic, pollType, seqPollInputItems)
|
||||
if err != nil {
|
||||
return common.LocalError("Failed to add poll to topic", w, r, user) // TODO: Might need to be an internal error as it could leave phantom polls?
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
CREATE TABLE [polls] (
|
||||
[pollID] int not null IDENTITY,
|
||||
[parentID] int DEFAULT 0 not null,
|
||||
[parentTable] nvarchar (100) DEFAULT 'topics' not null,
|
||||
[type] int DEFAULT 0 not null,
|
||||
[options] nvarchar (MAX) not null,
|
||||
[votes] int DEFAULT 0 not null,
|
||||
|
@ -1,5 +1,7 @@
|
||||
CREATE TABLE `polls` (
|
||||
`pollID` int not null AUTO_INCREMENT,
|
||||
`parentID` int DEFAULT 0 not null,
|
||||
`parentTable` varchar(100) DEFAULT 'topics' not null,
|
||||
`type` int DEFAULT 0 not null,
|
||||
`options` text not null,
|
||||
`votes` int DEFAULT 0 not null,
|
||||
|
@ -1,5 +1,7 @@
|
||||
CREATE TABLE `polls` (
|
||||
`pollID` serial not null,
|
||||
`parentID` int DEFAULT 0 not null,
|
||||
`parentTable` varchar (100) DEFAULT 'topics' not null,
|
||||
`type` int DEFAULT 0 not null,
|
||||
`options` json not null,
|
||||
`votes` int DEFAULT 0 not null,
|
||||
|
264
template_list.go
264
template_list.go
@ -352,207 +352,223 @@ var topic_alt_20 = []byte(`
|
||||
<div class="rowblock post_container">
|
||||
`)
|
||||
var topic_alt_21 = []byte(`
|
||||
<article class="rowitem passive deletable_block editable_parent post_item top_post">
|
||||
<form id="poll_`)
|
||||
var topic_alt_22 = []byte(`_form" action="/poll/vote/`)
|
||||
var topic_alt_23 = []byte(`?session=`)
|
||||
var topic_alt_24 = []byte(`" method="post"></form>
|
||||
<article class="rowitem passive deletable_block editable_parent post_item top_post hide_on_edit">
|
||||
<div class="userinfo" aria-label="The information on the poster">
|
||||
<div class="avatar_item" style="background-image: url(`)
|
||||
var topic_alt_22 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
var topic_alt_25 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
<a href="`)
|
||||
var topic_alt_23 = []byte(`" class="the_name" rel="author">`)
|
||||
var topic_alt_24 = []byte(`</a>
|
||||
var topic_alt_26 = []byte(`" class="the_name" rel="author">`)
|
||||
var topic_alt_27 = []byte(`</a>
|
||||
`)
|
||||
var topic_alt_25 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||
var topic_alt_26 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_27 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||
var topic_alt_28 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_29 = []byte(`
|
||||
var topic_alt_28 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||
var topic_alt_29 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_30 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||
var topic_alt_31 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_32 = []byte(`
|
||||
</div>
|
||||
<div class="content_container">
|
||||
<div class="hide_on_edit topic_content user_content" itemprop="text">
|
||||
<div id="poll_voter_`)
|
||||
var topic_alt_33 = []byte(`" class="content_container poll_voter">
|
||||
<div class="topic_content user_content">
|
||||
`)
|
||||
var topic_alt_30 = []byte(`
|
||||
var topic_alt_34 = []byte(`
|
||||
<div class="poll_option">
|
||||
<input id="poll_option_`)
|
||||
var topic_alt_31 = []byte(`" name="poll_option_input" type="checkbox" value="`)
|
||||
var topic_alt_32 = []byte(`" />
|
||||
<input form="poll_`)
|
||||
var topic_alt_35 = []byte(`_form" id="poll_option_`)
|
||||
var topic_alt_36 = []byte(`" name="poll_option_input" type="checkbox" value="`)
|
||||
var topic_alt_37 = []byte(`" />
|
||||
<label class="poll_option_label" for="poll_option_`)
|
||||
var topic_alt_33 = []byte(`">
|
||||
var topic_alt_38 = []byte(`">
|
||||
<div class="sel"></div>
|
||||
</label>
|
||||
<span class="poll_option_text">`)
|
||||
var topic_alt_34 = []byte(`</span>
|
||||
var topic_alt_39 = []byte(`</span>
|
||||
</div>
|
||||
`)
|
||||
var topic_alt_35 = []byte(`
|
||||
var topic_alt_40 = []byte(`
|
||||
<div class="poll_buttons">
|
||||
<button form="poll_`)
|
||||
var topic_alt_41 = []byte(`_form" class="poll_vote_button">Vote</button>
|
||||
<button class="poll_results_button">Results</button>
|
||||
<a href="#"><button class="poll_cancel_button">Cancel</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="poll_results_`)
|
||||
var topic_alt_42 = []byte(`" class="content_container poll_results auto_hide">
|
||||
<div class="topic_content user_content"></div>
|
||||
</div>
|
||||
</article>
|
||||
`)
|
||||
var topic_alt_36 = []byte(`
|
||||
var topic_alt_43 = []byte(`
|
||||
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item top_post" aria-label="The opening post for this topic">
|
||||
<div class="userinfo" aria-label="The information on the poster">
|
||||
<div class="avatar_item" style="background-image: url(`)
|
||||
var topic_alt_37 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
var topic_alt_44 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
<a href="`)
|
||||
var topic_alt_38 = []byte(`" class="the_name" rel="author">`)
|
||||
var topic_alt_39 = []byte(`</a>
|
||||
var topic_alt_45 = []byte(`" class="the_name" rel="author">`)
|
||||
var topic_alt_46 = []byte(`</a>
|
||||
`)
|
||||
var topic_alt_40 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||
var topic_alt_41 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_42 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||
var topic_alt_43 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_44 = []byte(`
|
||||
var topic_alt_47 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||
var topic_alt_48 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_49 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||
var topic_alt_50 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_51 = []byte(`
|
||||
</div>
|
||||
<div class="content_container">
|
||||
<div class="hide_on_edit topic_content user_content" itemprop="text">`)
|
||||
var topic_alt_45 = []byte(`</div>
|
||||
var topic_alt_52 = []byte(`</div>
|
||||
<textarea name="topic_content" class="show_on_edit topic_content_input">`)
|
||||
var topic_alt_46 = []byte(`</textarea>
|
||||
var topic_alt_53 = []byte(`</textarea>
|
||||
<div class="button_container">
|
||||
`)
|
||||
var topic_alt_47 = []byte(`<a href="/topic/like/submit/`)
|
||||
var topic_alt_48 = []byte(`?session=`)
|
||||
var topic_alt_49 = []byte(`" class="action_button like_item add_like" aria-label="Like this post" data-action="like"></a>`)
|
||||
var topic_alt_50 = []byte(`<a href="/topic/edit/`)
|
||||
var topic_alt_51 = []byte(`" class="action_button open_edit" aria-label="Edit this post" data-action="edit"></a>`)
|
||||
var topic_alt_52 = []byte(`<a href="/topic/delete/submit/`)
|
||||
var topic_alt_53 = []byte(`?session=`)
|
||||
var topic_alt_54 = []byte(`" class="action_button delete_item" aria-label="Delete this post" data-action="delete"></a>`)
|
||||
var topic_alt_55 = []byte(`<a href='/topic/unlock/submit/`)
|
||||
var topic_alt_56 = []byte(`?session=`)
|
||||
var topic_alt_57 = []byte(`' class="action_button unlock_item" data-action="unlock"></a>`)
|
||||
var topic_alt_58 = []byte(`<a href='/topic/lock/submit/`)
|
||||
var topic_alt_59 = []byte(`?session=`)
|
||||
var topic_alt_60 = []byte(`' class="action_button lock_item" data-action="lock"></a>`)
|
||||
var topic_alt_61 = []byte(`<a href='/topic/unstick/submit/`)
|
||||
var topic_alt_62 = []byte(`?session=`)
|
||||
var topic_alt_63 = []byte(`' class="action_button unpin_item" data-action="unpin"></a>`)
|
||||
var topic_alt_64 = []byte(`<a href='/topic/stick/submit/`)
|
||||
var topic_alt_65 = []byte(`?session=`)
|
||||
var topic_alt_66 = []byte(`' class="action_button pin_item" data-action="pin"></a>`)
|
||||
var topic_alt_67 = []byte(`<a href="/users/ips/?ip=`)
|
||||
var topic_alt_68 = []byte(`" title="IP Address" class="action_button ip_item_button hide_on_big" aria-label="This user's IP" data-action="ip"></a>`)
|
||||
var topic_alt_69 = []byte(`
|
||||
var topic_alt_54 = []byte(`<a href="/topic/like/submit/`)
|
||||
var topic_alt_55 = []byte(`?session=`)
|
||||
var topic_alt_56 = []byte(`" class="action_button like_item add_like" aria-label="Like this post" data-action="like"></a>`)
|
||||
var topic_alt_57 = []byte(`<a href="/topic/edit/`)
|
||||
var topic_alt_58 = []byte(`" class="action_button open_edit" aria-label="Edit this post" data-action="edit"></a>`)
|
||||
var topic_alt_59 = []byte(`<a href="/topic/delete/submit/`)
|
||||
var topic_alt_60 = []byte(`?session=`)
|
||||
var topic_alt_61 = []byte(`" class="action_button delete_item" aria-label="Delete this post" data-action="delete"></a>`)
|
||||
var topic_alt_62 = []byte(`<a href='/topic/unlock/submit/`)
|
||||
var topic_alt_63 = []byte(`?session=`)
|
||||
var topic_alt_64 = []byte(`' class="action_button unlock_item" data-action="unlock"></a>`)
|
||||
var topic_alt_65 = []byte(`<a href='/topic/lock/submit/`)
|
||||
var topic_alt_66 = []byte(`?session=`)
|
||||
var topic_alt_67 = []byte(`' class="action_button lock_item" data-action="lock"></a>`)
|
||||
var topic_alt_68 = []byte(`<a href='/topic/unstick/submit/`)
|
||||
var topic_alt_69 = []byte(`?session=`)
|
||||
var topic_alt_70 = []byte(`' class="action_button unpin_item" data-action="unpin"></a>`)
|
||||
var topic_alt_71 = []byte(`<a href='/topic/stick/submit/`)
|
||||
var topic_alt_72 = []byte(`?session=`)
|
||||
var topic_alt_73 = []byte(`' class="action_button pin_item" data-action="pin"></a>`)
|
||||
var topic_alt_74 = []byte(`<a href="/users/ips/?ip=`)
|
||||
var topic_alt_75 = []byte(`" title="IP Address" class="action_button ip_item_button hide_on_big" aria-label="This user's IP" data-action="ip"></a>`)
|
||||
var topic_alt_76 = []byte(`
|
||||
<a href="/report/submit/`)
|
||||
var topic_alt_70 = []byte(`?session=`)
|
||||
var topic_alt_71 = []byte(`&type=topic" class="action_button report_item" aria-label="Report this post" data-action="report"></a>
|
||||
var topic_alt_77 = []byte(`?session=`)
|
||||
var topic_alt_78 = []byte(`&type=topic" class="action_button report_item" aria-label="Report this post" data-action="report"></a>
|
||||
<a href="#" class="action_button button_menu"></a>
|
||||
`)
|
||||
var topic_alt_72 = []byte(`
|
||||
var topic_alt_79 = []byte(`
|
||||
<div class="action_button_right`)
|
||||
var topic_alt_73 = []byte(` has_likes`)
|
||||
var topic_alt_74 = []byte(`">
|
||||
var topic_alt_80 = []byte(` has_likes`)
|
||||
var topic_alt_81 = []byte(`">
|
||||
`)
|
||||
var topic_alt_75 = []byte(`<a class="action_button like_count hide_on_micro">`)
|
||||
var topic_alt_76 = []byte(`</a>`)
|
||||
var topic_alt_77 = []byte(`
|
||||
var topic_alt_82 = []byte(`<a class="action_button like_count hide_on_micro">`)
|
||||
var topic_alt_83 = []byte(`</a>`)
|
||||
var topic_alt_84 = []byte(`
|
||||
<a class="action_button created_at hide_on_mobile">`)
|
||||
var topic_alt_78 = []byte(`</a>
|
||||
var topic_alt_85 = []byte(`</a>
|
||||
`)
|
||||
var topic_alt_79 = []byte(`<a href="/users/ips/?ip=`)
|
||||
var topic_alt_80 = []byte(`" title="IP Address" class="action_button ip_item hide_on_mobile">`)
|
||||
var topic_alt_81 = []byte(`</a>`)
|
||||
var topic_alt_82 = []byte(`
|
||||
var topic_alt_86 = []byte(`<a href="/users/ips/?ip=`)
|
||||
var topic_alt_87 = []byte(`" title="IP Address" class="action_button ip_item hide_on_mobile">`)
|
||||
var topic_alt_88 = []byte(`</a>`)
|
||||
var topic_alt_89 = []byte(`
|
||||
</div>
|
||||
</div>
|
||||
</div><div style="clear:both;"></div>
|
||||
</article>
|
||||
|
||||
`)
|
||||
var topic_alt_83 = []byte(`
|
||||
var topic_alt_90 = []byte(`
|
||||
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item `)
|
||||
var topic_alt_84 = []byte(`action_item`)
|
||||
var topic_alt_85 = []byte(`">
|
||||
var topic_alt_91 = []byte(`action_item`)
|
||||
var topic_alt_92 = []byte(`">
|
||||
<div class="userinfo" aria-label="The information on the poster">
|
||||
<div class="avatar_item" style="background-image: url(`)
|
||||
var topic_alt_86 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
var topic_alt_93 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
<a href="`)
|
||||
var topic_alt_87 = []byte(`" class="the_name" rel="author">`)
|
||||
var topic_alt_88 = []byte(`</a>
|
||||
var topic_alt_94 = []byte(`" class="the_name" rel="author">`)
|
||||
var topic_alt_95 = []byte(`</a>
|
||||
`)
|
||||
var topic_alt_89 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||
var topic_alt_90 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_91 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||
var topic_alt_92 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_93 = []byte(`
|
||||
var topic_alt_96 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||
var topic_alt_97 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_98 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||
var topic_alt_99 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_100 = []byte(`
|
||||
</div>
|
||||
<div class="content_container" `)
|
||||
var topic_alt_94 = []byte(`style="margin-left: 0px;"`)
|
||||
var topic_alt_95 = []byte(`>
|
||||
var topic_alt_101 = []byte(`style="margin-left: 0px;"`)
|
||||
var topic_alt_102 = []byte(`>
|
||||
`)
|
||||
var topic_alt_96 = []byte(`
|
||||
var topic_alt_103 = []byte(`
|
||||
<span class="action_icon" style="font-size: 18px;padding-right: 5px;">`)
|
||||
var topic_alt_97 = []byte(`</span>
|
||||
var topic_alt_104 = []byte(`</span>
|
||||
<span itemprop="text">`)
|
||||
var topic_alt_98 = []byte(`</span>
|
||||
var topic_alt_105 = []byte(`</span>
|
||||
`)
|
||||
var topic_alt_99 = []byte(`
|
||||
var topic_alt_106 = []byte(`
|
||||
<div class="editable_block user_content" itemprop="text">`)
|
||||
var topic_alt_100 = []byte(`</div>
|
||||
var topic_alt_107 = []byte(`</div>
|
||||
<div class="button_container">
|
||||
`)
|
||||
var topic_alt_101 = []byte(`<a href="/reply/like/submit/`)
|
||||
var topic_alt_102 = []byte(`?session=`)
|
||||
var topic_alt_103 = []byte(`" class="action_button like_item add_like" aria-label="Like this post" data-action="like"></a>`)
|
||||
var topic_alt_104 = []byte(`<a href="/reply/edit/submit/`)
|
||||
var topic_alt_105 = []byte(`?session=`)
|
||||
var topic_alt_106 = []byte(`" class="action_button edit_item" aria-label="Edit this post" data-action="edit"></a>`)
|
||||
var topic_alt_107 = []byte(`<a href="/reply/delete/submit/`)
|
||||
var topic_alt_108 = []byte(`?session=`)
|
||||
var topic_alt_109 = []byte(`" class="action_button delete_item" aria-label="Delete this post" data-action="delete"></a>`)
|
||||
var topic_alt_110 = []byte(`<a href="/users/ips/?ip=`)
|
||||
var topic_alt_111 = []byte(`" title="IP Address" class="action_button ip_item_button hide_on_big" aria-label="This user's IP Address" data-action="ip"></a>`)
|
||||
var topic_alt_112 = []byte(`
|
||||
var topic_alt_108 = []byte(`<a href="/reply/like/submit/`)
|
||||
var topic_alt_109 = []byte(`?session=`)
|
||||
var topic_alt_110 = []byte(`" class="action_button like_item add_like" aria-label="Like this post" data-action="like"></a>`)
|
||||
var topic_alt_111 = []byte(`<a href="/reply/edit/submit/`)
|
||||
var topic_alt_112 = []byte(`?session=`)
|
||||
var topic_alt_113 = []byte(`" class="action_button edit_item" aria-label="Edit this post" data-action="edit"></a>`)
|
||||
var topic_alt_114 = []byte(`<a href="/reply/delete/submit/`)
|
||||
var topic_alt_115 = []byte(`?session=`)
|
||||
var topic_alt_116 = []byte(`" class="action_button delete_item" aria-label="Delete this post" data-action="delete"></a>`)
|
||||
var topic_alt_117 = []byte(`<a href="/users/ips/?ip=`)
|
||||
var topic_alt_118 = []byte(`" title="IP Address" class="action_button ip_item_button hide_on_big" aria-label="This user's IP Address" data-action="ip"></a>`)
|
||||
var topic_alt_119 = []byte(`
|
||||
<a href="/report/submit/`)
|
||||
var topic_alt_113 = []byte(`?session=`)
|
||||
var topic_alt_114 = []byte(`&type=reply" class="action_button report_item" aria-label="Report this post" data-action="report"></a>
|
||||
var topic_alt_120 = []byte(`?session=`)
|
||||
var topic_alt_121 = []byte(`&type=reply" class="action_button report_item" aria-label="Report this post" data-action="report"></a>
|
||||
<a href="#" class="action_button button_menu"></a>
|
||||
`)
|
||||
var topic_alt_115 = []byte(`
|
||||
var topic_alt_122 = []byte(`
|
||||
<div class="action_button_right`)
|
||||
var topic_alt_116 = []byte(` has_likes`)
|
||||
var topic_alt_117 = []byte(`">
|
||||
var topic_alt_123 = []byte(` has_likes`)
|
||||
var topic_alt_124 = []byte(`">
|
||||
`)
|
||||
var topic_alt_118 = []byte(`<a class="action_button like_count hide_on_micro">`)
|
||||
var topic_alt_119 = []byte(`</a>`)
|
||||
var topic_alt_120 = []byte(`
|
||||
var topic_alt_125 = []byte(`<a class="action_button like_count hide_on_micro">`)
|
||||
var topic_alt_126 = []byte(`</a>`)
|
||||
var topic_alt_127 = []byte(`
|
||||
<a class="action_button created_at hide_on_mobile">`)
|
||||
var topic_alt_121 = []byte(`</a>
|
||||
var topic_alt_128 = []byte(`</a>
|
||||
`)
|
||||
var topic_alt_122 = []byte(`<a href="/users/ips/?ip=`)
|
||||
var topic_alt_123 = []byte(`" title="IP Address" class="action_button ip_item hide_on_mobile">`)
|
||||
var topic_alt_124 = []byte(`</a>`)
|
||||
var topic_alt_125 = []byte(`
|
||||
var topic_alt_129 = []byte(`<a href="/users/ips/?ip=`)
|
||||
var topic_alt_130 = []byte(`" title="IP Address" class="action_button ip_item hide_on_mobile">`)
|
||||
var topic_alt_131 = []byte(`</a>`)
|
||||
var topic_alt_132 = []byte(`
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
var topic_alt_126 = []byte(`
|
||||
var topic_alt_133 = []byte(`
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</article>
|
||||
`)
|
||||
var topic_alt_127 = []byte(`</div>
|
||||
var topic_alt_134 = []byte(`</div>
|
||||
|
||||
`)
|
||||
var topic_alt_128 = []byte(`
|
||||
var topic_alt_135 = []byte(`
|
||||
<div class="rowblock topic_reply_container">
|
||||
<div class="userinfo" aria-label="The information on the poster">
|
||||
<div class="avatar_item" style="background-image: url(`)
|
||||
var topic_alt_129 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
var topic_alt_136 = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
<a href="`)
|
||||
var topic_alt_130 = []byte(`" class="the_name" rel="author">`)
|
||||
var topic_alt_131 = []byte(`</a>
|
||||
var topic_alt_137 = []byte(`" class="the_name" rel="author">`)
|
||||
var topic_alt_138 = []byte(`</a>
|
||||
`)
|
||||
var topic_alt_132 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||
var topic_alt_133 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_134 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||
var topic_alt_135 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_136 = []byte(`
|
||||
var topic_alt_139 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">`)
|
||||
var topic_alt_140 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_141 = []byte(`<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level `)
|
||||
var topic_alt_142 = []byte(`</div><div class="tag_post"></div></div>`)
|
||||
var topic_alt_143 = []byte(`
|
||||
</div>
|
||||
<div class="rowblock topic_reply_form quick_create_form">
|
||||
<form id="reply_form" enctype="multipart/form-data" action="/reply/create/?session=`)
|
||||
var topic_alt_137 = []byte(`" method="post"></form>
|
||||
var topic_alt_144 = []byte(`" method="post"></form>
|
||||
<input form="reply_form" name="tid" value='`)
|
||||
var topic_alt_138 = []byte(`' type="hidden" />
|
||||
var topic_alt_145 = []byte(`' type="hidden" />
|
||||
<div class="formrow real_first_child">
|
||||
<div class="formitem">
|
||||
<textarea id="input_content" form="reply_form" name="reply-content" placeholder="What do you think?" required></textarea>
|
||||
@ -562,17 +578,17 @@ var topic_alt_138 = []byte(`' type="hidden" />
|
||||
<div class="formitem">
|
||||
<button form="reply_form" name="reply-button" class="formbutton">Create Reply</button>
|
||||
`)
|
||||
var topic_alt_139 = []byte(`
|
||||
var topic_alt_146 = []byte(`
|
||||
<input name="upload_files" form="reply_form" id="upload_files" multiple type="file" style="display: none;" />
|
||||
<label for="upload_files" class="formbutton add_file_button">Add File</label>
|
||||
<div id="upload_file_dock"></div>`)
|
||||
var topic_alt_140 = []byte(`
|
||||
var topic_alt_147 = []byte(`
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
var topic_alt_141 = []byte(`
|
||||
var topic_alt_148 = []byte(`
|
||||
|
||||
</main>
|
||||
|
||||
|
@ -128,264 +128,278 @@ w.Write(topic_alt_19)
|
||||
w.Write(topic_alt_20)
|
||||
if tmpl_topic_alt_vars.Poll.ID > 0 {
|
||||
w.Write(topic_alt_21)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||
w.Write(topic_alt_22)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||
w.Write(topic_alt_23)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_24)
|
||||
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
||||
w.Write(topic_alt_25)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
||||
w.Write(topic_alt_26)
|
||||
} else {
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
||||
w.Write(topic_alt_27)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
||||
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
||||
w.Write(topic_alt_28)
|
||||
}
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
||||
w.Write(topic_alt_29)
|
||||
} else {
|
||||
w.Write(topic_alt_30)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
||||
w.Write(topic_alt_31)
|
||||
}
|
||||
w.Write(topic_alt_32)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||
w.Write(topic_alt_33)
|
||||
if len(tmpl_topic_alt_vars.Poll.QuickOptions) != 0 {
|
||||
for _, item := range tmpl_topic_alt_vars.Poll.QuickOptions {
|
||||
w.Write(topic_alt_30)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_31)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_32)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_33)
|
||||
w.Write([]byte(item.Value))
|
||||
w.Write(topic_alt_34)
|
||||
}
|
||||
}
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||
w.Write(topic_alt_35)
|
||||
}
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_36)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_37)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_38)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
||||
w.Write([]byte(item.Value))
|
||||
w.Write(topic_alt_39)
|
||||
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
||||
w.Write(topic_alt_40)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
||||
w.Write(topic_alt_41)
|
||||
} else {
|
||||
w.Write(topic_alt_42)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
||||
w.Write(topic_alt_43)
|
||||
}
|
||||
}
|
||||
w.Write(topic_alt_40)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||
w.Write(topic_alt_41)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Poll.ID)))
|
||||
w.Write(topic_alt_42)
|
||||
}
|
||||
w.Write(topic_alt_43)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
||||
w.Write(topic_alt_44)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.ContentHTML))
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
||||
w.Write(topic_alt_45)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Content))
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
||||
w.Write(topic_alt_46)
|
||||
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
||||
w.Write(topic_alt_47)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
||||
w.Write(topic_alt_48)
|
||||
} else {
|
||||
w.Write(topic_alt_49)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
||||
w.Write(topic_alt_50)
|
||||
}
|
||||
w.Write(topic_alt_51)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.ContentHTML))
|
||||
w.Write(topic_alt_52)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Content))
|
||||
w.Write(topic_alt_53)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
||||
w.Write(topic_alt_47)
|
||||
w.Write(topic_alt_54)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_48)
|
||||
w.Write(topic_alt_55)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_49)
|
||||
w.Write(topic_alt_56)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditTopic {
|
||||
w.Write(topic_alt_50)
|
||||
w.Write(topic_alt_57)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_51)
|
||||
w.Write(topic_alt_58)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteTopic {
|
||||
w.Write(topic_alt_52)
|
||||
w.Write(topic_alt_59)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_53)
|
||||
w.Write(topic_alt_60)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_54)
|
||||
w.Write(topic_alt_61)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CloseTopic {
|
||||
if tmpl_topic_alt_vars.Topic.IsClosed {
|
||||
w.Write(topic_alt_55)
|
||||
w.Write(topic_alt_62)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_56)
|
||||
w.Write(topic_alt_63)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_57)
|
||||
w.Write(topic_alt_64)
|
||||
} else {
|
||||
w.Write(topic_alt_58)
|
||||
w.Write(topic_alt_65)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_59)
|
||||
w.Write(topic_alt_66)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_60)
|
||||
w.Write(topic_alt_67)
|
||||
}
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.PinTopic {
|
||||
if tmpl_topic_alt_vars.Topic.Sticky {
|
||||
w.Write(topic_alt_61)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_62)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_63)
|
||||
} else {
|
||||
w.Write(topic_alt_64)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_65)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_66)
|
||||
}
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_alt_67)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||
w.Write(topic_alt_68)
|
||||
}
|
||||
w.Write(topic_alt_69)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_70)
|
||||
w.Write(topic_alt_69)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_70)
|
||||
} else {
|
||||
w.Write(topic_alt_71)
|
||||
}
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_72)
|
||||
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_73)
|
||||
}
|
||||
w.Write(topic_alt_74)
|
||||
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
||||
w.Write(topic_alt_75)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount)))
|
||||
w.Write(topic_alt_76)
|
||||
}
|
||||
w.Write(topic_alt_77)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.RelativeCreatedAt))
|
||||
w.Write(topic_alt_78)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_alt_79)
|
||||
w.Write(topic_alt_74)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||
w.Write(topic_alt_80)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||
w.Write(topic_alt_81)
|
||||
w.Write(topic_alt_75)
|
||||
}
|
||||
w.Write(topic_alt_76)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_77)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_78)
|
||||
}
|
||||
w.Write(topic_alt_79)
|
||||
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
||||
w.Write(topic_alt_80)
|
||||
}
|
||||
w.Write(topic_alt_81)
|
||||
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
||||
w.Write(topic_alt_82)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount)))
|
||||
w.Write(topic_alt_83)
|
||||
}
|
||||
w.Write(topic_alt_84)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.RelativeCreatedAt))
|
||||
w.Write(topic_alt_85)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_alt_86)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||
w.Write(topic_alt_87)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||
w.Write(topic_alt_88)
|
||||
}
|
||||
w.Write(topic_alt_89)
|
||||
if len(tmpl_topic_alt_vars.ItemList) != 0 {
|
||||
for _, item := range tmpl_topic_alt_vars.ItemList {
|
||||
w.Write(topic_alt_83)
|
||||
if item.ActionType != "" {
|
||||
w.Write(topic_alt_84)
|
||||
}
|
||||
w.Write(topic_alt_85)
|
||||
w.Write([]byte(item.Avatar))
|
||||
w.Write(topic_alt_86)
|
||||
w.Write([]byte(item.UserLink))
|
||||
w.Write(topic_alt_87)
|
||||
w.Write([]byte(item.CreatedByName))
|
||||
w.Write(topic_alt_88)
|
||||
if item.Tag != "" {
|
||||
w.Write(topic_alt_89)
|
||||
w.Write([]byte(item.Tag))
|
||||
w.Write(topic_alt_90)
|
||||
} else {
|
||||
if item.ActionType != "" {
|
||||
w.Write(topic_alt_91)
|
||||
w.Write([]byte(strconv.Itoa(item.Level)))
|
||||
}
|
||||
w.Write(topic_alt_92)
|
||||
}
|
||||
w.Write([]byte(item.Avatar))
|
||||
w.Write(topic_alt_93)
|
||||
if item.ActionType != "" {
|
||||
w.Write([]byte(item.UserLink))
|
||||
w.Write(topic_alt_94)
|
||||
}
|
||||
w.Write([]byte(item.CreatedByName))
|
||||
w.Write(topic_alt_95)
|
||||
if item.ActionType != "" {
|
||||
if item.Tag != "" {
|
||||
w.Write(topic_alt_96)
|
||||
w.Write([]byte(item.ActionIcon))
|
||||
w.Write([]byte(item.Tag))
|
||||
w.Write(topic_alt_97)
|
||||
w.Write([]byte(item.ActionType))
|
||||
w.Write(topic_alt_98)
|
||||
} else {
|
||||
w.Write(topic_alt_98)
|
||||
w.Write([]byte(strconv.Itoa(item.Level)))
|
||||
w.Write(topic_alt_99)
|
||||
w.Write([]byte(item.ContentHtml))
|
||||
}
|
||||
w.Write(topic_alt_100)
|
||||
if item.ActionType != "" {
|
||||
w.Write(topic_alt_101)
|
||||
}
|
||||
w.Write(topic_alt_102)
|
||||
if item.ActionType != "" {
|
||||
w.Write(topic_alt_103)
|
||||
w.Write([]byte(item.ActionIcon))
|
||||
w.Write(topic_alt_104)
|
||||
w.Write([]byte(item.ActionType))
|
||||
w.Write(topic_alt_105)
|
||||
} else {
|
||||
w.Write(topic_alt_106)
|
||||
w.Write([]byte(item.ContentHtml))
|
||||
w.Write(topic_alt_107)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
||||
w.Write(topic_alt_101)
|
||||
w.Write(topic_alt_108)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_102)
|
||||
w.Write(topic_alt_109)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_103)
|
||||
w.Write(topic_alt_110)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditReply {
|
||||
w.Write(topic_alt_104)
|
||||
w.Write(topic_alt_111)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_105)
|
||||
w.Write(topic_alt_112)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_106)
|
||||
w.Write(topic_alt_113)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteReply {
|
||||
w.Write(topic_alt_107)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_108)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_109)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_alt_110)
|
||||
w.Write([]byte(item.IPAddress))
|
||||
w.Write(topic_alt_111)
|
||||
}
|
||||
w.Write(topic_alt_112)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_113)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_114)
|
||||
}
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_115)
|
||||
if item.LikeCount > 0 {
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_116)
|
||||
}
|
||||
w.Write(topic_alt_117)
|
||||
if item.LikeCount > 0 {
|
||||
w.Write(topic_alt_118)
|
||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||
w.Write(topic_alt_119)
|
||||
}
|
||||
w.Write(topic_alt_120)
|
||||
w.Write([]byte(item.RelativeCreatedAt))
|
||||
w.Write(topic_alt_121)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_alt_117)
|
||||
w.Write([]byte(item.IPAddress))
|
||||
w.Write(topic_alt_118)
|
||||
}
|
||||
w.Write(topic_alt_119)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_120)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_121)
|
||||
}
|
||||
w.Write(topic_alt_122)
|
||||
w.Write([]byte(item.IPAddress))
|
||||
if item.LikeCount > 0 {
|
||||
w.Write(topic_alt_123)
|
||||
w.Write([]byte(item.IPAddress))
|
||||
}
|
||||
w.Write(topic_alt_124)
|
||||
}
|
||||
if item.LikeCount > 0 {
|
||||
w.Write(topic_alt_125)
|
||||
}
|
||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||
w.Write(topic_alt_126)
|
||||
}
|
||||
}
|
||||
w.Write(topic_alt_127)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
||||
w.Write([]byte(item.RelativeCreatedAt))
|
||||
w.Write(topic_alt_128)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Avatar))
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_alt_129)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link))
|
||||
w.Write([]byte(item.IPAddress))
|
||||
w.Write(topic_alt_130)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Name))
|
||||
w.Write([]byte(item.IPAddress))
|
||||
w.Write(topic_alt_131)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Tag != "" {
|
||||
}
|
||||
w.Write(topic_alt_132)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Tag))
|
||||
}
|
||||
w.Write(topic_alt_133)
|
||||
} else {
|
||||
}
|
||||
}
|
||||
w.Write(topic_alt_134)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.Level)))
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
||||
w.Write(topic_alt_135)
|
||||
}
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Avatar))
|
||||
w.Write(topic_alt_136)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link))
|
||||
w.Write(topic_alt_137)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Name))
|
||||
w.Write(topic_alt_138)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.UploadFiles {
|
||||
if tmpl_topic_alt_vars.CurrentUser.Tag != "" {
|
||||
w.Write(topic_alt_139)
|
||||
}
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Tag))
|
||||
w.Write(topic_alt_140)
|
||||
}
|
||||
} else {
|
||||
w.Write(topic_alt_141)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.Level)))
|
||||
w.Write(topic_alt_142)
|
||||
}
|
||||
w.Write(topic_alt_143)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_144)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_145)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.UploadFiles {
|
||||
w.Write(topic_alt_146)
|
||||
}
|
||||
w.Write(topic_alt_147)
|
||||
}
|
||||
w.Write(topic_alt_148)
|
||||
w.Write(footer_0)
|
||||
w.Write([]byte(common.BuildWidget("footer",tmpl_topic_alt_vars.Header)))
|
||||
w.Write(footer_1)
|
||||
|
@ -24,25 +24,34 @@
|
||||
|
||||
<div class="rowblock post_container">
|
||||
{{if .Poll.ID}}
|
||||
<article class="rowitem passive deletable_block editable_parent post_item top_post">
|
||||
<form id="poll_{{.Poll.ID}}_form" action="/poll/vote/{{.Poll.ID}}?session={{.CurrentUser.Session}}" method="post"></form>
|
||||
<article class="rowitem passive deletable_block editable_parent post_item top_post hide_on_edit">
|
||||
<div class="userinfo" aria-label="The information on the poster">
|
||||
<div class="avatar_item" style="background-image: url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
||||
<a href="{{.Topic.UserLink}}" class="the_name" rel="author">{{.Topic.CreatedByName}}</a>
|
||||
{{if .Topic.Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.Topic.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">Level {{.Topic.Level}}</div><div class="tag_post"></div></div>{{end}}
|
||||
</div>
|
||||
<div class="content_container">
|
||||
<div class="hide_on_edit topic_content user_content" itemprop="text">
|
||||
<div id="poll_voter_{{.Poll.ID}}" class="content_container poll_voter">
|
||||
<div class="topic_content user_content">
|
||||
{{range .Poll.QuickOptions}}
|
||||
<div class="poll_option">
|
||||
<input id="poll_option_{{.ID}}" name="poll_option_input" type="checkbox" value="{{.ID}}" />
|
||||
<input form="poll_{{$.Poll.ID}}_form" id="poll_option_{{.ID}}" name="poll_option_input" type="checkbox" value="{{.ID}}" />
|
||||
<label class="poll_option_label" for="poll_option_{{.ID}}">
|
||||
<div class="sel"></div>
|
||||
</label>
|
||||
<span class="poll_option_text">{{.Value}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="poll_buttons">
|
||||
<button form="poll_{{.Poll.ID}}_form" class="poll_vote_button">Vote</button>
|
||||
<button class="poll_results_button">Results</button>
|
||||
<a href="#"><button class="poll_cancel_button">Cancel</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="poll_results_{{.Poll.ID}}" class="content_container poll_results auto_hide">
|
||||
<div class="topic_content user_content"></div>
|
||||
</div>
|
||||
</article>
|
||||
{{end}}
|
||||
<article itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item top_post" aria-label="The opening post for this topic">
|
||||
|
@ -510,9 +510,6 @@ input[type=checkbox] + label {
|
||||
border: 1px solid var(--element-border-color);
|
||||
background-color: var(--element-background-color);
|
||||
}
|
||||
/*input[type=checkbox]:checked + label {
|
||||
background-color: purple;
|
||||
}*/
|
||||
input[type=checkbox]:checked + label .sel {
|
||||
display: inline-block;
|
||||
width: 5px;
|
||||
@ -535,8 +532,34 @@ input[type=checkbox]:checked + label .sel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input[type=checkbox] + label.poll_option_label {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
input[type=checkbox]:checked + label.poll_option_label .sel {
|
||||
display: inline-block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-left: 3px;
|
||||
background: var(--element-border-color);
|
||||
}
|
||||
/*.poll_option {
|
||||
margin-bottom: 3px;
|
||||
}*/
|
||||
.poll_option_text {
|
||||
display: inline-block;
|
||||
margin-left: 3px;
|
||||
font-size: 15px;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
color: var(--light-text-color);
|
||||
}
|
||||
.poll_buttons {
|
||||
display: flex;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.poll_buttons button {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.formbutton {
|
||||
|
Loading…
Reference in New Issue
Block a user