You can now disable slugs.

Split ops.log into ops.log and requests.log
Moved the logs into the logs directory.
Moved more password validation logic in the registration route into WeakPassword().
Tweaked the WeakPassword algorithm to cover more cases and to reduce the number of false positives.
Fixed the error grammer in WeakPassword now that the linter isn't bothering me about that anymore.
Fixed BuildGuildURL().
Removed some commented logging logic.
Bad requests are no longer logged to the console.
All bad routes are logged now.
We now track the instance uptime on the Control Panel Debug Page.
Added the executables for Linux to the .gitignore file.
Added GopherJS as a dependency.

Began work on transpiling WeakPassword to JavaScript in use in the client-side logic.
This commit is contained in:
Azareal 2018-04-03 05:34:07 +01:00
parent 74e09efb63
commit b32e8d6c21
32 changed files with 265 additions and 303 deletions

4
.gitignore vendored
View File

@ -10,10 +10,10 @@ attachs/*
uploads/avatar_* uploads/avatar_*
uploads/socialgroup_* uploads/socialgroup_*
backups/*.sql backups/*.sql
logs/*.log
node_modules/* node_modules/*
bin/* bin/*
out/* out/*
logs/*
*.exe *.exe
*.exe~ *.exe~
*.prof *.prof
@ -21,3 +21,5 @@ logs/*
.DS_Store .DS_Store
.vscode/launch.json .vscode/launch.json
config.go config.go
Gosora
Install

View File

@ -10,7 +10,7 @@ If you dislike it, please give us some feedback on how to make it better! We're
# Features # Features
Basic Forum Functionality. All of the little things you would expect of any forum software. E.g. Common Moderation features, modlogs, theme system, avatars, bbcode parser, markdown parser, report system, per-forum permissions, group permissions and so on. Standard Forum Functionality. All of the little things you would expect of any forum software. E.g. Common Moderation features, modlogs, theme system, avatars, bbcode parser, markdown parser, report system, per-forum permissions, group permissions and so on.
Custom Pages. Under development. The Control Panel portion is incomplete, but you can create them by hand today. They're basically html/templates templates in the /pages/ folder. Custom Pages. Under development. The Control Panel portion is incomplete, but you can create them by hand today. They're basically html/templates templates in the /pages/ folder.
@ -122,6 +122,8 @@ go get -u github.com/fsnotify/fsnotify
go get -u gopkg.in/src-d/go-git.v4/... go get -u gopkg.in/src-d/go-git.v4/...
go get -u github.com/gopherjs/gopherjs
go generate go generate

16
client/main.go Normal file
View File

@ -0,0 +1,16 @@
package main
import (
"../common"
"github.com/gopherjs/gopherjs/js"
)
func main() {
js.Global.Set("weakPassword", func(password string, username string, email string) string {
err := common.WeakPassword(password, username, email)
if err != nil {
return err.Error()
}
return ""
})
}

View File

@ -144,7 +144,7 @@ func BlankForum(fid int, link string, name string, desc string, active bool, pre
} }
func BuildForumURL(slug string, fid int) string { func BuildForumURL(slug string, fid int) string {
if slug == "" { if slug == "" || !Config.BuildSlugs {
return "/forum/" + strconv.Itoa(fid) return "/forum/" + strconv.Itoa(fid)
} }
return "/forum/" + slug + "." + strconv.Itoa(fid) return "/forum/" + slug + "." + strconv.Itoa(fid)

View File

@ -7,6 +7,13 @@ import (
"time" "time"
) )
// TODO: Implement this and use it
// TODO: Allow resources in spots other than /static/ and possibly even external domains (e.g. CDNs)
type HeaderResource struct {
Path string
Preload bool
}
type HeaderVars struct { type HeaderVars struct {
NoticeList []string NoticeList []string
Scripts []string Scripts []string

View File

@ -1,7 +1,6 @@
package common package common
import ( import (
//"fmt"
"bytes" "bytes"
"html" "html"
"net/url" "net/url"
@ -295,26 +294,18 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
} }
// Search for URLs, mentions and hashlinks in the messages... // Search for URLs, mentions and hashlinks in the messages...
//log.Print("Parser Loop!")
var msgbytes = []byte(msg) var msgbytes = []byte(msg)
var outbytes []byte var outbytes []byte
msgbytes = append(msgbytes, SpaceGap...) msgbytes = append(msgbytes, SpaceGap...)
//log.Printf("string(msgbytes) %+v\n", `"`+string(msgbytes)+`"`)
var lastItem = 0 var lastItem = 0
var i = 0 var i = 0
for ; len(msgbytes) > (i + 1); i++ { for ; len(msgbytes) > (i + 1); i++ {
//log.Print("Index: ",i)
//log.Print("Index Item: ",msgbytes[i])
//log.Print("string(msgbytes[i]): ",string(msgbytes[i]))
//log.Print("End Index")
if (i == 0 && (msgbytes[0] > 32)) || ((msgbytes[i] < 33) && (msgbytes[i+1] > 32)) { if (i == 0 && (msgbytes[0] > 32)) || ((msgbytes[i] < 33) && (msgbytes[i+1] > 32)) {
//log.Print("IN ",msgbytes[i])
if (i != 0) || msgbytes[i] < 33 { if (i != 0) || msgbytes[i] < 33 {
i++ i++
} }
if msgbytes[i] == '#' { if msgbytes[i] == '#' {
//log.Print("IN #")
if bytes.Equal(msgbytes[i+1:i+5], []byte("tid-")) { if bytes.Equal(msgbytes[i+1:i+5], []byte("tid-")) {
outbytes = append(outbytes, msgbytes[lastItem:i]...) outbytes = append(outbytes, msgbytes[lastItem:i]...)
i += 5 i += 5
@ -337,13 +328,6 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
outbytes = append(outbytes, tidBit...) outbytes = append(outbytes, tidBit...)
outbytes = append(outbytes, UrlClose...) outbytes = append(outbytes, UrlClose...)
lastItem = i lastItem = i
//log.Print("string(msgbytes): ",string(msgbytes))
//log.Print("msgbytes: ",msgbytes)
//log.Print("msgbytes[lastItem - 1]: ",msgbytes[lastItem - 1])
//log.Print("lastItem - 1: ",lastItem - 1)
//log.Print("msgbytes[lastItem]: ",msgbytes[lastItem])
//log.Print("lastItem: ",lastItem)
} else if bytes.Equal(msgbytes[i+1:i+5], []byte("rid-")) { } else if bytes.Equal(msgbytes[i+1:i+5], []byte("rid-")) {
outbytes = append(outbytes, msgbytes[lastItem:i]...) outbytes = append(outbytes, msgbytes[lastItem:i]...)
i += 5 i += 5
@ -391,7 +375,6 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
// TODO: Forum Shortcode Link // TODO: Forum Shortcode Link
} }
} else if msgbytes[i] == '@' { } else if msgbytes[i] == '@' {
//log.Print("IN @")
outbytes = append(outbytes, msgbytes[lastItem:i]...) outbytes = append(outbytes, msgbytes[lastItem:i]...)
i++ i++
start := i start := i
@ -415,19 +398,20 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
outbytes = append(outbytes, uidBit...) outbytes = append(outbytes, uidBit...)
outbytes = append(outbytes, UrlClose...) outbytes = append(outbytes, UrlClose...)
lastItem = i lastItem = i
} else if msgbytes[i] == 'h' || msgbytes[i] == 'f' || msgbytes[i] == 'g' { } else if msgbytes[i] == 'h' || msgbytes[i] == 'f' || msgbytes[i] == 'g' || msgbytes[i] == '/' {
//log.Print("IN hfg")
if msgbytes[i+1] == 't' && msgbytes[i+2] == 't' && msgbytes[i+3] == 'p' { if msgbytes[i+1] == 't' && msgbytes[i+2] == 't' && msgbytes[i+3] == 'p' {
if msgbytes[i+4] == 's' && msgbytes[i+5] == ':' && msgbytes[i+6] == '/' && msgbytes[i+7] == '/' { if msgbytes[i+4] == 's' && msgbytes[i+5] == ':' && msgbytes[i+6] == '/' {
// Do nothing // Do nothing
} else if msgbytes[i+4] == ':' && msgbytes[i+5] == '/' && msgbytes[i+6] == '/' { } else if msgbytes[i+4] == ':' && msgbytes[i+5] == '/' {
// Do nothing // Do nothing
} else { } else {
continue continue
} }
} else if msgbytes[i+1] == 't' && msgbytes[i+2] == 'p' && msgbytes[i+3] == ':' && msgbytes[i+4] == '/' && msgbytes[i+5] == '/' { } else if msgbytes[i+1] == 't' && msgbytes[i+2] == 'p' && msgbytes[i+3] == ':' && msgbytes[i+4] == '/' {
// Do nothing // Do nothing
} else if msgbytes[i+1] == 'i' && msgbytes[i+2] == 't' && msgbytes[i+3] == ':' && msgbytes[i+4] == '/' && msgbytes[i+5] == '/' { } else if msgbytes[i+1] == 'i' && msgbytes[i+2] == 't' && msgbytes[i+3] == ':' && msgbytes[i+4] == '/' {
// Do nothing
} else if msgbytes[i+1] == '/' {
// Do nothing // Do nothing
} else { } else {
continue continue
@ -438,10 +422,6 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
urlLen := PartialURLBytesLen(msgbytes[i:]) urlLen := PartialURLBytesLen(msgbytes[i:])
if msgbytes[i+urlLen] > 32 { // space and invisibles if msgbytes[i+urlLen] > 32 { // space and invisibles
//log.Print("INVALID URL") //log.Print("INVALID URL")
//log.Print("msgbytes[i+urlLen]: ", msgbytes[i+urlLen])
//log.Print("string(msgbytes[i+urlLen]): ", string(msgbytes[i+urlLen]))
//log.Print("msgbytes[i:i+urlLen]: ", msgbytes[i:i+urlLen])
//log.Print("string(msgbytes[i:i+urlLen]): ", string(msgbytes[i:i+urlLen]))
outbytes = append(outbytes, InvalidURL...) outbytes = append(outbytes, InvalidURL...)
i += urlLen i += urlLen
continue continue
@ -454,66 +434,7 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
continue continue
} }
if media.Type == "attach" { // TODO: Reduce the amount of code duplication
outbytes = append(outbytes, imageOpen...)
outbytes = append(outbytes, []byte(media.URL+"?sectionID="+strconv.Itoa(sectionID)+"&sectionType="+sectionType)...)
outbytes = append(outbytes, imageOpen2...)
outbytes = append(outbytes, []byte(media.URL+"?sectionID="+strconv.Itoa(sectionID)+"&sectionType="+sectionType)...)
outbytes = append(outbytes, imageClose...)
i += urlLen
lastItem = i
continue
} else if media.Type == "image" {
outbytes = append(outbytes, imageOpen...)
outbytes = append(outbytes, []byte(media.URL)...)
outbytes = append(outbytes, imageOpen2...)
outbytes = append(outbytes, []byte(media.URL)...)
outbytes = append(outbytes, imageClose...)
i += urlLen
lastItem = i
continue
} else if media.Type == "raw" {
outbytes = append(outbytes, []byte(media.Body)...)
i += urlLen
lastItem = i
continue
} else if media.Type != "" {
outbytes = append(outbytes, unknownMedia...)
i += urlLen
continue
}
outbytes = append(outbytes, UrlOpen...)
outbytes = append(outbytes, msgbytes[i:i+urlLen]...)
outbytes = append(outbytes, UrlOpen2...)
outbytes = append(outbytes, msgbytes[i:i+urlLen]...)
outbytes = append(outbytes, UrlClose...)
i += urlLen
lastItem = i
} else if msgbytes[i] == '/' && msgbytes[i+1] == '/' {
outbytes = append(outbytes, msgbytes[lastItem:i]...)
urlLen := PartialURLBytesLen(msgbytes[i:])
if msgbytes[i+urlLen] > 32 { // space and invisibles
//log.Print("INVALID URL")
//log.Print("msgbytes[i+urlLen]: ", msgbytes[i+urlLen])
//log.Print("string(msgbytes[i+urlLen]): ", string(msgbytes[i+urlLen]))
//log.Print("msgbytes[i:i+urlLen]: ", msgbytes[i:i+urlLen])
//log.Print("string(msgbytes[i:i+urlLen]): ", string(msgbytes[i:i+urlLen]))
outbytes = append(outbytes, InvalidURL...)
i += urlLen
continue
}
//log.Print("VALID URL")
//log.Print("msgbytes[i:i+urlLen]: ", msgbytes[i:i+urlLen])
//log.Print("string(msgbytes[i:i+urlLen]): ", string(msgbytes[i:i+urlLen]))
media, ok := parseMediaBytes(msgbytes[i : i+urlLen])
if !ok {
outbytes = append(outbytes, InvalidURL...)
i += urlLen
continue
}
if media.Type == "attach" { if media.Type == "attach" {
outbytes = append(outbytes, imageOpen...) outbytes = append(outbytes, imageOpen...)
outbytes = append(outbytes, []byte(media.URL+"?sectionID="+strconv.Itoa(sectionID)+"&sectionType="+sectionType)...) outbytes = append(outbytes, []byte(media.URL+"?sectionID="+strconv.Itoa(sectionID)+"&sectionType="+sectionType)...)
@ -555,11 +476,6 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
} }
if lastItem != i && len(outbytes) != 0 { if lastItem != i && len(outbytes) != 0 {
//log.Print("lastItem: ", msgbytes[lastItem])
//log.Print("lastItem index: ", lastItem)
//log.Print("i: ", i)
//log.Print("lastItem to end: ", msgbytes[lastItem:])
//log.Print("-----")
calclen := len(msgbytes) - 10 calclen := len(msgbytes) - 10
if calclen <= lastItem { if calclen <= lastItem {
calclen = lastItem calclen = lastItem
@ -567,8 +483,6 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
outbytes = append(outbytes, msgbytes[lastItem:calclen]...) outbytes = append(outbytes, msgbytes[lastItem:calclen]...)
msg = string(outbytes) msg = string(outbytes)
} }
//log.Print(`"`+string(outbytes)+`"`)
//log.Print("msg",`"`+msg+`"`)
msg = strings.Replace(msg, "\n", "<br>", -1) msg = strings.Replace(msg, "\n", "<br>", -1)
msg = RunSshook("parse_assign", msg) msg = RunSshook("parse_assign", msg)
@ -705,14 +619,10 @@ func parseMediaBytes(data []byte) (media MediaEmbed, ok bool) {
return media, false return media, false
} }
//log.Print("url ", url)
hostname := url.Hostname() hostname := url.Hostname()
scheme := url.Scheme scheme := url.Scheme
port := url.Port() port := url.Port()
//log.Print("hostname ", hostname)
//log.Print("scheme ", scheme)
query := url.Query() query := url.Query()
//log.Printf("query %+v\n", query)
var samesite = hostname == "localhost" || hostname == Site.URL var samesite = hostname == "localhost" || hostname == Site.URL
if samesite { if samesite {
@ -728,14 +638,9 @@ func parseMediaBytes(data []byte) (media MediaEmbed, ok bool) {
} }
path := url.EscapedPath() path := url.EscapedPath()
//log.Print("path", path)
pathFrags := strings.Split(path, "/") pathFrags := strings.Split(path, "/")
//log.Printf("pathFrags %+v\n", pathFrags)
//log.Print("scheme ", scheme)
//log.Print("hostname ", hostname)
if len(pathFrags) >= 2 { if len(pathFrags) >= 2 {
if samesite && pathFrags[1] == "attachs" && (scheme == "http" || scheme == "https") { if samesite && pathFrags[1] == "attachs" && (scheme == "http" || scheme == "https") {
//log.Print("Attachment")
media.Type = "attach" media.Type = "attach"
var sport string var sport string
// ? - Assumes the sysadmin hasn't mixed up the two standard ports // ? - Assumes the sysadmin hasn't mixed up the two standard ports

View File

@ -67,6 +67,7 @@ type config struct {
StaffCSS string // ? - Move this into the settings table? Might be better to implement this as Group CSS StaffCSS string // ? - Move this into the settings table? Might be better to implement this as Group CSS
DefaultForum int // The forum posts go in by default, this used to be covered by the Uncategorised Forum, but we want to replace it with a more robust solution. Make this a setting? DefaultForum int // The forum posts go in by default, this used to be covered by the Uncategorised Forum, but we want to replace it with a more robust solution. Make this a setting?
MinifyTemplates bool MinifyTemplates bool
BuildSlugs bool // TODO: Make this a setting?
ServerCount int ServerCount int
Noavatar string // ? - Move this into the settings table? Noavatar string // ? - Move this into the settings table?

View File

@ -388,7 +388,7 @@ func BlankTopic() *Topic {
} }
func BuildTopicURL(slug string, tid int) string { func BuildTopicURL(slug string, tid int) string {
if slug == "" { if slug == "" || !Config.BuildSlugs {
return "/topic/" + strconv.Itoa(tid) return "/topic/" + strconv.Itoa(tid)
} }
return "/topic/" + slug + "." + strconv.Itoa(tid) return "/topic/" + slug + "." + strconv.Itoa(tid)

View File

@ -426,7 +426,7 @@ func BlankUser() *User {
// TODO: Write unit tests for this // TODO: Write unit tests for this
func BuildProfileURL(slug string, uid int) string { func BuildProfileURL(slug string, uid int) string {
if slug == "" { if slug == "" || !Config.BuildSlugs {
return "/user/" + strconv.Itoa(uid) return "/user/" + strconv.Itoa(uid)
} }
return "/user/" + slug + "." + strconv.Itoa(uid) return "/user/" + slug + "." + strconv.Itoa(uid)

View File

@ -184,6 +184,10 @@ func ConvertFriendlyUnit(num int) (int, string) {
// TODO: Make slugs optional for certain languages across the entirety of Gosora? // TODO: Make slugs optional for certain languages across the entirety of Gosora?
// TODO: Let plugins replace NameToSlug and the URL building logic with their own // TODO: Let plugins replace NameToSlug and the URL building logic with their own
func NameToSlug(name string) (slug string) { func NameToSlug(name string) (slug string) {
// TODO: Do we want this reliant on config file flags? This might complicate tests and oddball uses
if !Config.BuildSlugs {
return ""
}
name = strings.TrimSpace(name) name = strings.TrimSpace(name)
name = strings.Replace(name, " ", " ", -1) name = strings.Replace(name, " ", " ", -1)
@ -204,12 +208,25 @@ func NameToSlug(name string) (slug string) {
} }
// TODO: Write a test for this // TODO: Write a test for this
func WeakPassword(password string) error { func WeakPassword(password string, username string, email string) error {
if len(password) < 8 { lowPassword := strings.ToLower(password)
return errors.New("your password needs to be at-least eight characters long") switch {
case password == "":
return errors.New("You didn't put in a password.")
case strings.Contains(lowPassword, strings.ToLower(username)) && len(username) > 3:
return errors.New("You can't use your username in your password.")
case strings.Contains(lowPassword, strings.ToLower(email)):
return errors.New("You can't use your email in your password.")
case len(password) < 8:
return errors.New("Your password needs to be at-least eight characters long")
} }
if strings.Contains(lowPassword, "test") || /*strings.Contains(password,"123456") || */ strings.Contains(password, "123") || strings.Contains(lowPassword, "password") || strings.Contains(lowPassword, "qwerty") || strings.Contains(lowPassword, "fuck") || strings.Contains(lowPassword, "love") {
return errors.New("You may not have 'test', '123', 'password', 'qwerty', 'love' or 'fuck' in your password")
}
var charMap = make(map[rune]int) var charMap = make(map[rune]int)
var numbers /*letters, */, symbols, upper, lower int var numbers, symbols, upper, lower int
for _, char := range password { for _, char := range password {
charItem, ok := charMap[char] charItem, ok := charMap[char]
if ok { if ok {
@ -220,7 +237,6 @@ func WeakPassword(password string) error {
charMap[char] = charItem charMap[char] = charItem
if unicode.IsLetter(char) { if unicode.IsLetter(char) {
//letters++
if unicode.IsUpper(char) { if unicode.IsUpper(char) {
upper++ upper++
} else { } else {
@ -233,25 +249,22 @@ func WeakPassword(password string) error {
} }
} }
// TODO: Disable the linter on these and fix up the grammar
if numbers == 0 { if numbers == 0 {
return errors.New("you don't have any numbers in your password") return errors.New("You don't have any numbers in your password")
} }
/*if letters == 0 {
return errors.New("You don't have any letters in your password.")
}*/
if upper == 0 { if upper == 0 {
return errors.New("you don't have any uppercase characters in your password") return errors.New("You don't have any uppercase characters in your password")
} }
if lower == 0 { if lower == 0 {
return errors.New("you don't have any lowercase characters in your password") return errors.New("You don't have any lowercase characters in your password")
} }
if (len(password) / 2) > len(charMap) { if len(password) < 18 {
return errors.New("you don't have enough unique characters in your password") if (len(password) / 2) > len(charMap) {
} return errors.New("You don't have enough unique characters in your password")
}
if strings.Contains(strings.ToLower(password), "test") || /*strings.Contains(strings.ToLower(password),"123456") || */ strings.Contains(strings.ToLower(password), "123") || strings.Contains(strings.ToLower(password), "password") || strings.Contains(strings.ToLower(password), "qwerty") { } else if (len(password) / 3) > len(charMap) {
return errors.New("you may not have 'test', '123', 'password' or 'qwerty' in your password") // Be a little lenient on the number of unique characters for long passwords
return errors.New("You don't have enough unique characters in your password")
} }
return nil return nil
} }
@ -372,7 +385,7 @@ func GetLevels(maxLevel int) []float64 {
} }
func BuildSlug(slug string, id int) string { func BuildSlug(slug string, id int) string {
if slug == "" { if slug == "" || !Config.BuildSlugs {
return strconv.Itoa(id) return strconv.Itoa(id)
} }
return slug + "." + strconv.Itoa(id) return slug + "." + strconv.Itoa(id)

View File

@ -359,8 +359,8 @@ func RouteMemberList(w http.ResponseWriter, r *http.Request, user common.User) c
pi := MemberListPage{"Guild Member List", user, headerVars, guildMembers, guildItem, 0, 0} pi := MemberListPage{"Guild Member List", user, headerVars, guildMembers, guildItem, 0, 0}
// A plugin with plugins. Pluginception! // A plugin with plugins. Pluginception!
if common.RunPreRenderHook("pre_render_guilds_member_list", w, r, &user, &pi) { if common.RunPreRenderHook("pre_render_guilds_member_list", w, r, &user, &pi) {
return nil return nil
} }
err = common.RunThemeTemplate(headerVars.Theme.Name, "guilds_member_list", pi, w) err = common.RunThemeTemplate(headerVars.Theme.Name, "guilds_member_list", pi, w)
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
@ -379,10 +379,10 @@ func UnattachForum(fid int) error {
} }
func BuildGuildURL(slug string, id int) string { func BuildGuildURL(slug string, id int) string {
if slug == "" { if slug == "" || !common.Config.BuildSlugs {
return "/guild/" + slug + "." + strconv.Itoa(id) return "/guild/" + strconv.Itoa(id)
} }
return "/guild/" + strconv.Itoa(id) return "/guild/" + slug + "." + strconv.Itoa(id)
} }
/* /*

View File

@ -8,6 +8,7 @@ import (
"strconv" "strconv"
"sync" "sync"
"errors" "errors"
"os"
"net/http" "net/http"
"./common" "./common"
@ -491,11 +492,17 @@ func (writ *WriterIntercept) GetCode() int {
type GenRouter struct { type GenRouter struct {
UploadHandler func(http.ResponseWriter, *http.Request) UploadHandler func(http.ResponseWriter, *http.Request)
extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError
requestLogger *log.Logger
sync.RWMutex sync.RWMutex
} }
func NewGenRouter(uploads http.Handler) *GenRouter { func NewGenRouter(uploads http.Handler) (*GenRouter, error) {
f, err := os.OpenFile("./logs/requests.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755)
if err != nil {
return nil, err
}
return &GenRouter{ return &GenRouter{
UploadHandler: func(w http.ResponseWriter, req *http.Request) { UploadHandler: func(w http.ResponseWriter, req *http.Request) {
writ := NewWriterIntercept(w) writ := NewWriterIntercept(w)
@ -506,7 +513,8 @@ func NewGenRouter(uploads http.Handler) *GenRouter {
} }
}, },
extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError), extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError),
} requestLogger: log.New(f, "", log.LstdFlags),
}, nil
} }
func (router *GenRouter) handleError(err common.RouteError, w http.ResponseWriter, r *http.Request, user common.User) { func (router *GenRouter) handleError(err common.RouteError, w http.ResponseWriter, r *http.Request, user common.User) {
@ -554,7 +562,7 @@ func (router *GenRouter) DumpRequest(req *http.Request, prepend string) {
} }
} }
log.Print(prepend + router.requestLogger.Print(prepend +
"\nUA: " + router.StripNewlines(req.UserAgent()) + "\n" + "\nUA: " + router.StripNewlines(req.UserAgent()) + "\n" +
"Method: " + router.StripNewlines(req.Method) + "\n" + heads + "Method: " + router.StripNewlines(req.Method) + "\n" + heads +
"req.Host: " + router.StripNewlines(req.Host) + "\n" + "req.Host: " + router.StripNewlines(req.Host) + "\n" +
@ -564,8 +572,11 @@ func (router *GenRouter) DumpRequest(req *http.Request, prepend string) {
"req.RemoteAddr: " + req.RemoteAddr + "\n") "req.RemoteAddr: " + req.RemoteAddr + "\n")
} }
func (router *GenRouter) SuspiciousRequest(req *http.Request) { func (router *GenRouter) SuspiciousRequest(req *http.Request, prepend string) {
router.DumpRequest(req,"Suspicious Request") if prepend != "" {
prepend += "\n"
}
router.DumpRequest(req,prepend+"Suspicious Request")
counters.AgentViewCounter.Bump(27) counters.AgentViewCounter.Bump(27)
} }
@ -600,14 +611,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// TODO: Cover more suspicious strings and at a lower layer than this // TODO: Cover more suspicious strings and at a lower layer than this
for _, char := range req.URL.Path { for _, char := range req.URL.Path {
if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) { if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) {
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"")
break break
} }
} }
lowerPath := strings.ToLower(req.URL.Path) lowerPath := strings.ToLower(req.URL.Path)
// TODO: Flag any requests which has a dot with anything but a number after that // 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(lowerPath,".php") || strings.Contains(lowerPath,".asp") || strings.Contains(lowerPath,".cgi") || strings.Contains(lowerPath,".py") || strings.Contains(lowerPath,".sql") || strings.Contains(lowerPath,".action") { 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") || strings.Contains(lowerPath,".action") {
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"")
} }
var prefix, extraData string var prefix, extraData string
@ -630,7 +641,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
log.Print("before PreRoute") router.requestLogger.Print("before PreRoute")
} }
// Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like. // Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like.
@ -676,9 +687,9 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// TODO: Test this // TODO: Test this
items = items[:0] items = items[:0]
indices = indices[:0] indices = indices[:0]
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"")
log.Print("UA Buffer: ", buffer) router.requestLogger.Print("UA Buffer: ", buffer)
log.Print("UA Buffer String: ", string(buffer)) router.requestLogger.Print("UA Buffer String: ", string(buffer))
break break
} }
} }
@ -695,7 +706,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
} }
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
log.Print("parsed agent: ", agent) router.requestLogger.Print("parsed agent: ", agent)
} }
var os string var os string
@ -717,8 +728,8 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
os = "unknown" os = "unknown"
} }
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
log.Print("os: ", os) router.requestLogger.Print("os: ", os)
log.Printf("items: %+v\n",items) router.requestLogger.Printf("items: %+v\n",items)
} }
// Special handling // Special handling
@ -737,7 +748,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
agent = "internetexplorer" agent = "internetexplorer"
} }
case "zgrab": case "zgrab":
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"Vulnerability Scanner")
} }
if agent == "" { if agent == "" {
@ -783,8 +794,9 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
log.Print("after PreRoute") router.requestLogger.Print(
log.Print("routeMapEnum: ", routeMapEnum) "after PreRoute\n" +
"routeMapEnum: ", routeMapEnum)
} }
var err common.RouteError var err common.RouteError
@ -1801,7 +1813,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
handle, ok := RouteMap[common.Config.DefaultRoute] handle, ok := RouteMap[common.Config.DefaultRoute]
if !ok { if !ok {
// TODO: Make this a startup error not a runtime one // TODO: Make this a startup error not a runtime one
log.Print("Unable to find the default route") router.requestLogger.Print("Unable to find the default route")
common.NotFound(w,req,nil) common.NotFound(w,req,nil)
return return
} }
@ -1824,10 +1836,11 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
// TODO: Log all bad routes for the admin to figure out where users are going wrong?
lowerPath := strings.ToLower(req.URL.Path) lowerPath := strings.ToLower(req.URL.Path)
if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") || strings.Contains(lowerPath,"//") || strings.Contains(lowerPath,"\\\\") || strings.Contains(lowerPath,"wp") || strings.Contains(lowerPath,"wordpress") || strings.Contains(lowerPath,"config") || strings.Contains(lowerPath,"setup") || strings.Contains(lowerPath,"install") || strings.Contains(lowerPath,"update") || strings.Contains(lowerPath,"php") { if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") || strings.Contains(lowerPath,"//") || strings.Contains(lowerPath,"\\\\") || strings.Contains(lowerPath,"wp") || strings.Contains(lowerPath,"wordpress") || strings.Contains(lowerPath,"config") || strings.Contains(lowerPath,"setup") || strings.Contains(lowerPath,"install") || strings.Contains(lowerPath,"update") || strings.Contains(lowerPath,"php") {
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"Bad Route")
} else {
router.DumpRequest(req,"Bad Route")
} }
counters.RouteViewCounter.Bump(104) counters.RouteViewCounter.Bump(104)
common.NotFound(w,req,nil) common.NotFound(w,req,nil)

View File

@ -78,7 +78,10 @@ func gloinit() (err error) {
return err return err
} }
router = NewGenRouter(http.FileServer(http.Dir("./uploads"))) router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
return err
}
gloinited = true gloinited = true
return nil return nil
} }
@ -142,13 +145,17 @@ func BenchmarkTopicAdminRouteParallel(b *testing.B) {
func BenchmarkTopicAdminRouteParallelWithRouter(b *testing.B) { func BenchmarkTopicAdminRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
var err error
if !gloinited { if !gloinited {
err := gloinit() err = gloinit()
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
router = NewGenRouter(http.FileServer(http.Dir("./uploads"))) router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false
@ -260,13 +267,17 @@ func BenchmarkTopicGuestRouteParallelDebugMode(b *testing.B) {
func BenchmarkTopicGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkTopicGuestRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
var err error
if !gloinited { if !gloinited {
err := gloinit() err = gloinit()
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
router = NewGenRouter(http.FileServer(http.Dir("./uploads"))) router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false
@ -301,13 +312,17 @@ func BenchmarkTopicGuestRouteParallelWithRouter(b *testing.B) {
func BenchmarkBadRouteGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkBadRouteGuestRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
var err error
if !gloinited { if !gloinited {
err := gloinit() err = gloinit()
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
router = NewGenRouter(http.FileServer(http.Dir("./uploads"))) router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false
@ -330,13 +345,17 @@ func BenchmarkBadRouteGuestRouteParallelWithRouter(b *testing.B) {
func BenchmarkTopicsGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkTopicsGuestRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
var err error
if !gloinited { if !gloinited {
err := gloinit() err = gloinit()
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
router = NewGenRouter(http.FileServer(http.Dir("./uploads"))) router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false
@ -363,13 +382,17 @@ func BenchmarkTopicsGuestRouteParallelWithRouter(b *testing.B) {
func BenchmarkForumsGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkForumsGuestRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
var err error
if !gloinited { if !gloinited {
err := gloinit() err = gloinit()
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
router = NewGenRouter(http.FileServer(http.Dir("./uploads"))) router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false
@ -396,13 +419,17 @@ func BenchmarkForumsGuestRouteParallelWithRouter(b *testing.B) {
func BenchmarkForumGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkForumGuestRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
var err error
if !gloinited { if !gloinited {
err := gloinit() err = gloinit()
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
} }
router = NewGenRouter(http.FileServer(http.Dir("./uploads"))) router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false

View File

@ -31,6 +31,8 @@ go get -u github.com/fsnotify/fsnotify
echo "Installing Go Git" echo "Installing Go Git"
go get -u gopkg.in/src-d/go-git.v4/... go get -u gopkg.in/src-d/go-git.v4/...
echo "Installing GopherJS"
go get -u github.com/gopherjs/gopherjs
echo "Building the installer" echo "Building the installer"
cd ./install cd ./install

View File

@ -92,6 +92,13 @@ if %errorlevel% neq 0 (
exit /b %errorlevel% exit /b %errorlevel%
) )
echo Installing GopherJS
go get -u github.com/gopherjs/gopherjs
if %errorlevel% neq 0 (
pause
exit /b %errorlevel%
)
echo Building the installer echo Building the installer
go generate go generate

View File

@ -148,6 +148,7 @@ func init() {
common.Config.StaffCSS = "staff_post" common.Config.StaffCSS = "staff_post"
common.Config.DefaultForum = 2 common.Config.DefaultForum = 2
common.Config.MinifyTemplates = true common.Config.MinifyTemplates = true
common.Config.BuildSlugs = true
common.Config.ServerCount = 1 // Experimental: Enable Cross-Server Synchronisation and several other features common.Config.ServerCount = 1 // Experimental: Enable Cross-Server Synchronisation and several other features
//common.Config.Noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png" //common.Config.Noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png"

1
logs/filler.txt Normal file
View File

@ -0,0 +1 @@
This file is here so that Git will include this folder in the repository.

View File

@ -182,7 +182,7 @@ func main() {
// TODO: Have a file for each run with the time/date the server started as the file name? // TODO: Have a file for each run with the time/date the server started as the file name?
// TODO: Log panics with recover() // TODO: Log panics with recover()
f, err := os.OpenFile("./ops.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755) f, err := os.OpenFile("./logs/ops.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -367,7 +367,10 @@ func main() {
}() }()
log.Print("Initialising the router") log.Print("Initialising the router")
router = NewGenRouter(http.FileServer(http.Dir("./uploads"))) router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
log.Fatal(err)
}
log.Print("Initialising the plugins") log.Print("Initialising the plugins")
common.InitPlugins() common.InitPlugins()

View File

@ -822,6 +822,7 @@ func TestProfileReplyStore(t *testing.T) {
func TestSlugs(t *testing.T) { func TestSlugs(t *testing.T) {
var res string var res string
var msgList []MEPair var msgList []MEPair
common.Config.BuildSlugs = true // Flip this switch, otherwise all the tests will fail
msgList = addMEPair(msgList, "Unknown", "unknown") msgList = addMEPair(msgList, "Unknown", "unknown")
msgList = addMEPair(msgList, "Unknown2", "unknown2") msgList = addMEPair(msgList, "Unknown2", "unknown2")

View File

@ -8,7 +8,6 @@
*/ */
package main package main
//import "time"
import ( import (
"database/sql" "database/sql"
"log" "log"

View File

@ -2567,10 +2567,24 @@ func routePanelDebug(w http.ResponseWriter, r *http.Request, user common.User) c
return ferr return ferr
} }
uptime := "..." var uptime string
upDuration := time.Since(startTime)
hours := int(upDuration.Hours())
minutes := int(upDuration.Minutes())
if hours > 24 {
days := hours / 24
hours -= days * 24
uptime += strconv.Itoa(days) + "d"
uptime += strconv.Itoa(hours) + "h"
} else if hours >= 1 {
uptime += strconv.Itoa(hours) + "h"
}
uptime += strconv.Itoa(minutes) + "m"
dbStats := db.Stats() dbStats := db.Stats()
openConnCount := dbStats.OpenConnections openConnCount := dbStats.OpenConnections
// Disk I/O? // Disk I/O?
// TODO: Fetch the adapter from Builder rather than getting it from a global?
pi := common.PanelDebugPage{common.GetTitlePhrase("panel_debug"), user, headerVars, stats, "debug", uptime, openConnCount, dbAdapter} pi := common.PanelDebugPage{common.GetTitlePhrase("panel_debug"), user, headerVars, stats, "debug", uptime, openConnCount, dbAdapter}
return panelRenderTemplate("panel_debug", w, r, user, &pi) return panelRenderTemplate("panel_debug", w, r, user, &pi)

View File

@ -1,11 +1,7 @@
package main package main
import ( import (
//"log"
//"fmt"
"bytes" "bytes"
//"strings"
"math/rand" "math/rand"
"regexp" "regexp"
"strconv" "strconv"
@ -215,9 +211,6 @@ func bbcodeFullParse(msg string) string {
msgbytes := []byte(msg) msgbytes := []byte(msg)
msgbytes = append(msgbytes, common.SpaceGap...) msgbytes = append(msgbytes, common.SpaceGap...)
//log.Print("BBCode Simple Pre:","`"+string(msgbytes)+"`")
//log.Print("----")
for i := 0; i < len(msgbytes); i++ { for i := 0; i < len(msgbytes); i++ {
if msgbytes[i] == '[' { if msgbytes[i] == '[' {
if msgbytes[i+2] != ']' { if msgbytes[i+2] != ']' {
@ -248,12 +241,6 @@ func bbcodeFullParse(msg string) string {
hasC = false hasC = false
i += 7 i += 7
} }
//if msglen >= (i+6) {
// log.Print("boo")
// log.Print(msglen)
// log.Print(i+6)
// log.Print(string(msgbytes[i:i+6]))
//}
complexBbc = true complexBbc = true
} }
} else { } else {
@ -261,9 +248,6 @@ func bbcodeFullParse(msg string) string {
hasC = true hasC = true
i += 6 i += 6
} }
//if msglen >= (i+5) {
// log.Print("boo2: ", string(msgbytes[i:i+5]))
//}
complexBbc = true complexBbc = true
} }
} else if !hasC { } else if !hasC {
@ -314,8 +298,6 @@ func bbcodeFullParse(msg string) string {
i := 0 i := 0
var start, lastTag int var start, lastTag int
var outbytes []byte var outbytes []byte
//log.Print("BBCode Pre:","`"+string(msgbytes)+"`")
//log.Print("----")
for ; i < len(msgbytes); i++ { for ; i < len(msgbytes); i++ {
if msgbytes[i] == '[' { if msgbytes[i] == '[' {
if msgbytes[i+1] == 'u' { if msgbytes[i+1] == 'u' {
@ -330,18 +312,15 @@ func bbcodeFullParse(msg string) string {
} }
} }
} }
//log.Print("Outbytes:",`"`+string(outbytes)+`"`)
if lastTag != i { if lastTag != i {
outbytes = append(outbytes, msgbytes[lastTag:]...) outbytes = append(outbytes, msgbytes[lastTag:]...)
} }
if len(outbytes) != 0 { if len(outbytes) != 0 {
//log.Print("BBCode Post:",`"`+string(outbytes[0:len(outbytes) - 10])+`"`)
msg = string(outbytes[0 : len(outbytes)-10]) msg = string(outbytes[0 : len(outbytes)-10])
} else { } else {
msg = string(msgbytes[0 : len(msgbytes)-10]) msg = string(msgbytes[0 : len(msgbytes)-10])
} }
//log.Print("----")
//msg = bbcode_url.ReplaceAllString(msg,"<a href=\"$1$2//$3\" rel=\"nofollow\">$1$2//$3</i>") //msg = bbcode_url.ReplaceAllString(msg,"<a href=\"$1$2//$3\" rel=\"nofollow\">$1$2//$3</i>")
msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='nofollow'>$4</i>") msg = bbcodeURLLabel.ReplaceAllString(msg, "<a href='$1$2//$3' rel='nofollow'>$4</i>")
@ -359,11 +338,7 @@ func bbcodeParseURL(i int, start int, lastTag int, msgbytes []byte, outbytes []b
outbytes = append(outbytes, msgbytes[lastTag:i]...) outbytes = append(outbytes, msgbytes[lastTag:i]...)
i = start i = start
i += common.PartialURLBytesLen(msgbytes[start:]) i += common.PartialURLBytesLen(msgbytes[start:])
//log.Print("Partial Bytes: ", string(msgbytes[start:]))
//log.Print("-----")
if !bytes.Equal(msgbytes[i:i+6], []byte("[/url]")) { if !bytes.Equal(msgbytes[i:i+6], []byte("[/url]")) {
//log.Print("Invalid Bytes: ", string(msgbytes[i:i+6]))
//log.Print("-----")
outbytes = append(outbytes, common.InvalidURL...) outbytes = append(outbytes, common.InvalidURL...)
return i, start, lastTag, outbytes return i, start, lastTag, outbytes
} }
@ -416,7 +391,6 @@ func bbcodeParseRand(i int, start int, lastTag int, msgbytes []byte, outbytes []
} }
outbytes = append(outbytes, dat...) outbytes = append(outbytes, dat...)
//log.Print("Outputted the random number")
i += 7 i += 7
lastTag = i lastTag = i
return i, start, lastTag, outbytes return i, start, lastTag, outbytes

View File

@ -2,7 +2,6 @@ package main
//import "fmt" //import "fmt"
import ( import (
"log"
"strings" "strings"
"./common" "./common"
@ -51,7 +50,6 @@ func markdownParse(msg string) string {
if msg[len(msg)-1] == ' ' { if msg[len(msg)-1] == ' ' {
msg = msg[:len(msg)-1] msg = msg[:len(msg)-1]
} }
log.Print("final msg: ", msg)
return msg return msg
} }
@ -66,12 +64,6 @@ func _markdownParse(msg string, n int) string {
common.DebugLogf("Initial Message: %+v\n", strings.Replace(msg, "\r", "\\r", -1)) common.DebugLogf("Initial Message: %+v\n", strings.Replace(msg, "\r", "\\r", -1))
for index := 0; index < len(msg); index++ { for index := 0; index < len(msg); index++ {
//log.Print("--OUTER MARKDOWN LOOP START--")
//log.Print("index: ", index)
//log.Print("msg[index]: ", msg[index])
//log.Print("string(msg[index]): ", string(msg[index]))
//log.Printf("--OUTER MARKDOWN LOOP END--\n\n")
switch msg[index] { switch msg[index] {
// TODO: Do something slightly less hacky for skipping URLs // TODO: Do something slightly less hacky for skipping URLs
case '/': case '/':
@ -131,95 +123,53 @@ func _markdownParse(msg string, n int) string {
lastElement = index lastElement = index
index-- index--
case '*': case '*':
//log.Print("------")
//log.Print("[]byte(msg): ", []byte(msg))
//log.Print("len(msg): ", len(msg))
//log.Print("start index: ", index)
//log.Print("start msg[index]: ", msg[index])
//log.Print("start string(msg[index]): ", string(msg[index]))
//log.Print("start []byte(msg[:index]): ", []byte(msg[:index]))
var startIndex = index var startIndex = index
var italic = true var italic = true
var bold = false var bold = false
if (index + 2) < len(msg) { if (index + 2) < len(msg) {
//log.Print("start index + 1: ", index + 1)
//log.Print("start msg[index]: ", msg[index + 1])
//log.Print("start string(msg[index]): ", string(msg[index + 1]))
if msg[index+1] == '*' { if msg[index+1] == '*' {
//log.Print("two asterisks")
bold = true bold = true
index++ index++
if msg[index+1] != '*' { if msg[index+1] != '*' {
italic = false italic = false
} else { } else {
//log.Print("three asterisks")
index++ index++
} }
} }
} }
//log.Print("lastElement: ", lastElement)
//log.Print("startIndex: ", startIndex)
//log.Print("msg[startIndex]: ", msg[startIndex])
//log.Print("string(msg[startIndex]): ", string(msg[startIndex]))
//log.Print("preabrupt index: ", index)
//log.Print("preabrupt msg[index]: ", msg[index])
//log.Print("preabrupt string(msg[index]): ", string(msg[index]))
//log.Print("preabrupt []byte(msg[:index]): ", []byte(msg[:index]))
//log.Print("preabrupt msg[:index]: ", msg[:index])
// Does the string terminate abruptly? // Does the string terminate abruptly?
if (index + 1) >= len(msg) { if (index + 1) >= len(msg) {
break break
} }
index++ index++
//log.Print("preskip index: ", index)
//log.Print("preskip msg[index]: ", msg[index])
//log.Print("preskip string(msg[index]): ", string(msg[index]))
index = markdownSkipUntilAsterisk(msg, index) index = markdownSkipUntilAsterisk(msg, index)
if index >= len(msg) { if index >= len(msg) {
break break
} }
//log.Print("index: ", index)
//log.Print("[]byte(msg[:index]): ", []byte(msg[:index]))
//log.Print("msg[index]: ", msg[index])
sIndex := startIndex sIndex := startIndex
lIndex := index lIndex := index
if bold && italic { if bold && italic {
//log.Print("bold & italic final code")
if (index + 3) >= len(msg) { if (index + 3) >= len(msg) {
//log.Print("unclosed markdown element @ exit element")
outbytes = append(outbytes, msg[lastElement:startIndex]...) outbytes = append(outbytes, msg[lastElement:startIndex]...)
//outbytes = append(outbytes, markdownUnclosedElement...)
lastElement = startIndex lastElement = startIndex
break break
} }
index += 3 index += 3
sIndex += 3 sIndex += 3
} else if bold { } else if bold {
//log.Print("bold final code")
if (index + 2) >= len(msg) { if (index + 2) >= len(msg) {
//log.Print("true unclosed markdown element @ exit element")
outbytes = append(outbytes, msg[lastElement:startIndex]...) outbytes = append(outbytes, msg[lastElement:startIndex]...)
//outbytes = append(outbytes, markdownUnclosedElement...)
lastElement = startIndex lastElement = startIndex
break break
} }
index += 2 index += 2
sIndex += 2 sIndex += 2
} else { } else {
//log.Print("italic final code")
if (index + 1) >= len(msg) { if (index + 1) >= len(msg) {
//log.Print("true unclosed markdown element @ exit element")
outbytes = append(outbytes, msg[lastElement:startIndex]...) outbytes = append(outbytes, msg[lastElement:startIndex]...)
//outbytes = append(outbytes, markdownUnclosedElement...)
lastElement = startIndex lastElement = startIndex
break break
} }
@ -227,38 +177,18 @@ func _markdownParse(msg string, n int) string {
sIndex++ sIndex++
} }
//log.Print("sIndex: ", sIndex)
//log.Print("lIndex: ", lIndex)
if lIndex <= sIndex { if lIndex <= sIndex {
//log.Print("unclosed markdown element @ lIndex <= sIndex")
outbytes = append(outbytes, msg[lastElement:startIndex]...) outbytes = append(outbytes, msg[lastElement:startIndex]...)
//outbytes = append(outbytes, markdownUnclosedElement...)
lastElement = startIndex lastElement = startIndex
break break
} }
if sIndex < 0 || lIndex < 0 { if sIndex < 0 || lIndex < 0 {
//log.Print("unclosed markdown element @ sIndex < 0 || lIndex < 0")
outbytes = append(outbytes, msg[lastElement:startIndex]...) outbytes = append(outbytes, msg[lastElement:startIndex]...)
//outbytes = append(outbytes, markdownUnclosedElement...)
lastElement = startIndex lastElement = startIndex
break break
} }
//log.Print("final sIndex: ", sIndex)
//log.Print("final lIndex: ",lIndex)
//log.Print("final index: ", index)
//log.Print("final msg[index]: ", msg[index])
//log.Print("final string(msg[index]): ", string(msg[index]))
//log.Print("final msg[sIndex]: ", msg[sIndex])
//log.Print("final string(msg[sIndex]): ", string(msg[sIndex]))
//log.Print("final msg[lIndex]: ", msg[lIndex])
//log.Print("final string(msg[lIndex]): ", string(msg[lIndex]))
//log.Print("[]byte(msg[:sIndex]): ", []byte(msg[:sIndex]))
//log.Print("[]byte(msg[:lIndex]): ", []byte(msg[:lIndex]))
outbytes = append(outbytes, msg[lastElement:startIndex]...) outbytes = append(outbytes, msg[lastElement:startIndex]...)
if bold { if bold {
@ -292,17 +222,13 @@ func _markdownParse(msg string, n int) string {
//case 10: // newline //case 10: // newline
} }
} }
//log.Print("exit message loop")
if len(outbytes) == 0 { if len(outbytes) == 0 {
return msg return msg
//return msg[:len(msg)-1]
} else if lastElement < (len(msg) - 1) { } else if lastElement < (len(msg) - 1) {
msg = string(outbytes) + msg[lastElement:] msg = string(outbytes) + msg[lastElement:]
return msg return msg
//return msg[:len(msg)-1]
} }
//return string(outbytes[:len(outbytes)-1])
return string(outbytes) return string(outbytes)
} }

View File

@ -379,6 +379,19 @@ func createTables(adapter qgen.Adapter) error {
[]qgen.DBTableKey{}, []qgen.DBTableKey{},
) )
/*
qgen.Install.CreateTable("registration_logs", "", "",
[]qgen.DBTableColumn{
qgen.DBTableColumn{"username", "varchar", 100, false, false, ""},
qgen.DBTableColumn{"email", "varchar", 100, false, false, ""},
qgen.DBTableColumn{"failureReason", "varchar", 100, false, false, ""},
qgen.DBTableColumn{"success", "int", 0, false, false, "0"}, // Did this attempt succeed?
qgen.DBTableColumn{"doneAt", "createdAt", 0, false, false, ""},
},
[]qgen.DBTableKey{},
)
*/
qgen.Install.CreateTable("moderation_logs", "", "", qgen.Install.CreateTable("moderation_logs", "", "",
[]qgen.DBTableColumn{ []qgen.DBTableColumn{
qgen.DBTableColumn{"action", "varchar", 100, false, false, ""}, qgen.DBTableColumn{"action", "varchar", 100, false, false, ""},

View File

@ -226,6 +226,7 @@ import (
"strconv" "strconv"
"sync" "sync"
"errors" "errors"
"os"
"net/http" "net/http"
"./common" "./common"
@ -331,11 +332,17 @@ func (writ *WriterIntercept) GetCode() int {
type GenRouter struct { type GenRouter struct {
UploadHandler func(http.ResponseWriter, *http.Request) UploadHandler func(http.ResponseWriter, *http.Request)
extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError extraRoutes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError
requestLogger *log.Logger
sync.RWMutex sync.RWMutex
} }
func NewGenRouter(uploads http.Handler) *GenRouter { func NewGenRouter(uploads http.Handler) (*GenRouter, error) {
f, err := os.OpenFile("./logs/requests.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0755)
if err != nil {
return nil, err
}
return &GenRouter{ return &GenRouter{
UploadHandler: func(w http.ResponseWriter, req *http.Request) { UploadHandler: func(w http.ResponseWriter, req *http.Request) {
writ := NewWriterIntercept(w) writ := NewWriterIntercept(w)
@ -346,7 +353,8 @@ func NewGenRouter(uploads http.Handler) *GenRouter {
} }
}, },
extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError), extraRoutes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError),
} requestLogger: log.New(f, "", log.LstdFlags),
}, nil
} }
func (router *GenRouter) handleError(err common.RouteError, w http.ResponseWriter, r *http.Request, user common.User) { func (router *GenRouter) handleError(err common.RouteError, w http.ResponseWriter, r *http.Request, user common.User) {
@ -394,7 +402,7 @@ func (router *GenRouter) DumpRequest(req *http.Request, prepend string) {
} }
} }
log.Print(prepend + router.requestLogger.Print(prepend +
"\nUA: " + router.StripNewlines(req.UserAgent()) + "\n" + "\nUA: " + router.StripNewlines(req.UserAgent()) + "\n" +
"Method: " + router.StripNewlines(req.Method) + "\n" + heads + "Method: " + router.StripNewlines(req.Method) + "\n" + heads +
"req.Host: " + router.StripNewlines(req.Host) + "\n" + "req.Host: " + router.StripNewlines(req.Host) + "\n" +
@ -404,8 +412,11 @@ func (router *GenRouter) DumpRequest(req *http.Request, prepend string) {
"req.RemoteAddr: " + req.RemoteAddr + "\n") "req.RemoteAddr: " + req.RemoteAddr + "\n")
} }
func (router *GenRouter) SuspiciousRequest(req *http.Request) { func (router *GenRouter) SuspiciousRequest(req *http.Request, prepend string) {
router.DumpRequest(req,"Suspicious Request") if prepend != "" {
prepend += "\n"
}
router.DumpRequest(req,prepend+"Suspicious Request")
counters.AgentViewCounter.Bump({{.AllAgentMap.suspicious}}) counters.AgentViewCounter.Bump({{.AllAgentMap.suspicious}})
} }
@ -440,14 +451,14 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// TODO: Cover more suspicious strings and at a lower layer than this // TODO: Cover more suspicious strings and at a lower layer than this
for _, char := range req.URL.Path { for _, char := range req.URL.Path {
if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) { if char != '&' && !(char > 44 && char < 58) && char != '=' && char != '?' && !(char > 64 && char < 91) && char != '\\' && char != '_' && !(char > 96 && char < 123) {
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"")
break break
} }
} }
lowerPath := strings.ToLower(req.URL.Path) lowerPath := strings.ToLower(req.URL.Path)
// TODO: Flag any requests which has a dot with anything but a number after that // 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(lowerPath,".php") || strings.Contains(lowerPath,".asp") || strings.Contains(lowerPath,".cgi") || strings.Contains(lowerPath,".py") || strings.Contains(lowerPath,".sql") || strings.Contains(lowerPath,".action") { 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") || strings.Contains(lowerPath,".action") {
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"")
} }
var prefix, extraData string var prefix, extraData string
@ -470,7 +481,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
log.Print("before PreRoute") router.requestLogger.Print("before PreRoute")
} }
// Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like. // Track the user agents. Unfortunately, everyone pretends to be Mozilla, so this'll be a little less efficient than I would like.
@ -516,9 +527,9 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// TODO: Test this // TODO: Test this
items = items[:0] items = items[:0]
indices = indices[:0] indices = indices[:0]
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"")
log.Print("UA Buffer: ", buffer) router.requestLogger.Print("UA Buffer: ", buffer)
log.Print("UA Buffer String: ", string(buffer)) router.requestLogger.Print("UA Buffer String: ", string(buffer))
break break
} }
} }
@ -535,7 +546,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
} }
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
log.Print("parsed agent: ", agent) router.requestLogger.Print("parsed agent: ", agent)
} }
var os string var os string
@ -557,8 +568,8 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
os = "unknown" os = "unknown"
} }
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
log.Print("os: ", os) router.requestLogger.Print("os: ", os)
log.Printf("items: %+v\n",items) router.requestLogger.Printf("items: %+v\n",items)
} }
// Special handling // Special handling
@ -577,7 +588,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
agent = "internetexplorer" agent = "internetexplorer"
} }
case "zgrab": case "zgrab":
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"Vulnerability Scanner")
} }
if agent == "" { if agent == "" {
@ -623,8 +634,9 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
if common.Dev.SuperDebug { if common.Dev.SuperDebug {
log.Print("after PreRoute") router.requestLogger.Print(
log.Print("routeMapEnum: ", routeMapEnum) "after PreRoute\n" +
"routeMapEnum: ", routeMapEnum)
} }
var err common.RouteError var err common.RouteError
@ -671,7 +683,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
handle, ok := RouteMap[common.Config.DefaultRoute] handle, ok := RouteMap[common.Config.DefaultRoute]
if !ok { if !ok {
// TODO: Make this a startup error not a runtime one // TODO: Make this a startup error not a runtime one
log.Print("Unable to find the default route") router.requestLogger.Print("Unable to find the default route")
common.NotFound(w,req,nil) common.NotFound(w,req,nil)
return return
} }
@ -694,10 +706,11 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
// TODO: Log all bad routes for the admin to figure out where users are going wrong?
lowerPath := strings.ToLower(req.URL.Path) lowerPath := strings.ToLower(req.URL.Path)
if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") || strings.Contains(lowerPath,"//") || strings.Contains(lowerPath,"\\\\") || strings.Contains(lowerPath,"wp") || strings.Contains(lowerPath,"wordpress") || strings.Contains(lowerPath,"config") || strings.Contains(lowerPath,"setup") || strings.Contains(lowerPath,"install") || strings.Contains(lowerPath,"update") || strings.Contains(lowerPath,"php") { if strings.Contains(lowerPath,"admin") || strings.Contains(lowerPath,"sql") || strings.Contains(lowerPath,"manage") || strings.Contains(lowerPath,"//") || strings.Contains(lowerPath,"\\\\") || strings.Contains(lowerPath,"wp") || strings.Contains(lowerPath,"wordpress") || strings.Contains(lowerPath,"config") || strings.Contains(lowerPath,"setup") || strings.Contains(lowerPath,"install") || strings.Contains(lowerPath,"update") || strings.Contains(lowerPath,"php") {
router.SuspiciousRequest(req) router.SuspiciousRequest(req,"Bad Route")
} else {
router.DumpRequest(req,"Bad Route")
} }
counters.RouteViewCounter.Bump({{.AllRouteMap.BadRoute}}) counters.RouteViewCounter.Bump({{.AllRouteMap.BadRoute}})
common.NotFound(w,req,nil) common.NotFound(w,req,nil)

View File

@ -105,17 +105,8 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
} }
password := r.PostFormValue("password") password := r.PostFormValue("password")
switch password {
case "":
return common.LocalError("You didn't put in a password.", w, r, user)
case username:
return common.LocalError("You can't use your username as your password.", w, r, user)
case email:
return common.LocalError("You can't use your email as your password.", w, r, user)
}
// ? Move this into Create()? What if we want to programatically set weak passwords for tests? // ? Move this into Create()? What if we want to programatically set weak passwords for tests?
err := common.WeakPassword(password) err := common.WeakPassword(password, username, email)
if err != nil { if err != nil {
return common.LocalError(err.Error(), w, r, user) return common.LocalError(err.Error(), w, r, user)
} }

View File

@ -56,5 +56,5 @@ if %errorlevel% neq 0 (
echo Running Gosora echo Running Gosora
gosora.exe gosora.exe
rem Or you could redirect the output to a file rem Or you could redirect the output to a file
rem gosora.exe > ops.log 2>&1 rem gosora.exe > ./logs/ops.log 2>&1
pause pause

View File

@ -1,4 +1,6 @@
{ {
"DBVersion":"0", "DBVersion":"0",
"DynamicFileVersion":"0" "DynamicFileVersion":"0",
"MinGoVersion":"1.9",
"MinVersion":""
} }

View File

@ -29,4 +29,7 @@ echo "Updating fsnotify"
go get -u github.com/fsnotify/fsnotify go get -u github.com/fsnotify/fsnotify
echo "Updating Go Git" echo "Updating Go Git"
go get -u gopkg.in/src-d/go-git.v4/... go get -u gopkg.in/src-d/go-git.v4/...
echo "Updating GopherJS"
go get -u github.com/gopherjs/gopherjs

View File

@ -89,5 +89,12 @@ if %errorlevel% neq 0 (
exit /b %errorlevel% exit /b %errorlevel%
) )
echo Updating GopherJS
go get -u github.com/gopherjs/gopherjs
if %errorlevel% neq 0 (
pause
exit /b %errorlevel%
)
echo The dependencies were successfully updated echo The dependencies were successfully updated
pause pause

View File

@ -92,6 +92,13 @@ if %errorlevel% neq 0 (
exit /b %errorlevel% exit /b %errorlevel%
) )
echo Updating GopherJS
go get -u github.com/gopherjs/gopherjs
if %errorlevel% neq 0 (
pause
exit /b %errorlevel%
)
echo Building the updater echo Building the updater
go generate go generate

View File

@ -4,7 +4,9 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"os" "os"
"runtime"
"runtime/debug" "runtime/debug"
"syscall"
"gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4"
) )
@ -62,7 +64,17 @@ func updater(scanner *bufio.Scanner) error {
return err return err
} }
fmt.Println("Commit details:")
commit, err := repo.CommitObject(headRef.Hash()) commit, err := repo.CommitObject(headRef.Hash())
if err != nil {
return err
}
fmt.Println("Commit details:", commit)
switch runtime.GOOS {
case "windows":
err = syscall.Exec("./patcher.bat", []string{}, os.Environ())
default: //linux, etc.
err = syscall.Exec("./patcher-linux", []string{}, os.Environ())
}
return err return err
} }