Added an algorithm for sniffing out weak passwords upon registration.
Themes can now inject their own stylesheets and JavaScript files into the header. Added friendlier errors for developers / designers when something goes wrong in the system. Moved three queries to the query generator. _process_where() in the query generator now uses an arbitrary expression parser, thus allowing more complex constructs like IN. Began work on the widget system. Added SimpleLeftJoin and SimpleInnerJoin to the inline query builder. Added SimpleInsertSelect and SimpleInsertInnerJoin to the query generator. _process_columns() now supports parametisation. Fixed a bug in _process_set() where _ was considered an invalid character in column names. Fixed a typo in the interpreter template mapping for topics.
This commit is contained in:
parent
c4e109adb7
commit
1cc1e47582
|
@ -118,7 +118,11 @@ func init_plugins() {
|
|||
log.Print("Added plugin " + name)
|
||||
if body.Active {
|
||||
log.Print("Initialised plugin " + name)
|
||||
if plugins[name].Init != nil {
|
||||
plugins[name].Init()
|
||||
} else {
|
||||
log.Print("Plugin " + name + " doesn't have an initialiser.")
|
||||
}
|
||||
}
|
||||
}
|
||||
plugins_inited = true
|
||||
|
|
|
@ -6,6 +6,10 @@ import "errors"
|
|||
import "database/sql"
|
||||
import "./query_gen/lib"
|
||||
|
||||
var forums []Forum // The IDs for a forum tend to be low and sequential for the most part, so we can get more performance out of using a slice instead of a map AND it has better concurrency
|
||||
var forum_perms map[int]map[int]ForumPerms // [gid][fid]Perms
|
||||
var fstore ForumStore // :soon:
|
||||
var forumCapCount int
|
||||
var err_noforum = errors.New("This forum doesn't exist")
|
||||
|
||||
type ForumStore interface
|
||||
|
|
23
gen_mysql.go
23
gen_mysql.go
|
@ -21,6 +21,7 @@ var get_forums_stmt *sql.Stmt
|
|||
var get_forums_permissions_stmt *sql.Stmt
|
||||
var get_plugins_stmt *sql.Stmt
|
||||
var get_themes_stmt *sql.Stmt
|
||||
var get_widgets_stmt *sql.Stmt
|
||||
var is_plugin_active_stmt *sql.Stmt
|
||||
var get_users_stmt *sql.Stmt
|
||||
var is_theme_default_stmt *sql.Stmt
|
||||
|
@ -109,6 +110,8 @@ var delete_topic_stmt *sql.Stmt
|
|||
var delete_profile_reply_stmt *sql.Stmt
|
||||
var delete_forum_perms_by_forum_stmt *sql.Stmt
|
||||
var report_exists_stmt *sql.Stmt
|
||||
var add_forum_perms_to_forum_admins_stmt *sql.Stmt
|
||||
var notify_watchers_stmt *sql.Stmt
|
||||
|
||||
func gen_mysql() (err error) {
|
||||
if debug {
|
||||
|
@ -205,6 +208,12 @@ func gen_mysql() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing get_widgets statement.")
|
||||
get_widgets_stmt, err = db.Prepare("SELECT `position`,`side`,`type`,`active`,`location`,`data` FROM `widgets` ORDER BY position ASC")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing is_plugin_active statement.")
|
||||
is_plugin_active_stmt, err = db.Prepare("SELECT `active` FROM `plugins` WHERE `uname` = ?")
|
||||
if err != nil {
|
||||
|
@ -698,7 +707,7 @@ func gen_mysql() (err error) {
|
|||
}
|
||||
|
||||
log.Print("Preparing verify_email statement.")
|
||||
verify_email_stmt, err = db.Prepare("UPDATE `emails` SET `validated` = 1,`token` = '1' WHERE `email` = ? ")
|
||||
verify_email_stmt, err = db.Prepare("UPDATE `emails` SET `validated` = 1,`token` = '' WHERE `email` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -733,5 +742,17 @@ func gen_mysql() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing add_forum_perms_to_forum_admins statement.")
|
||||
add_forum_perms_to_forum_admins_stmt, err = db.Prepare("INSERT INTO `forums_permissions`(`gid`,`fid`,`preset`,`permissions`) SELECT `gid`, ? AS `fid`, ? AS `preset`, ? AS `permissions` FROM `users_groups` WHERE `is_admin` = 1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing notify_watchers statement.")
|
||||
notify_watchers_stmt, err = db.Prepare("INSERT INTO `activity_stream_matches`(`watcher`,`asid`) SELECT `activity_subscriptions`.`user`, `activity_stream`.`asid` FROM `activity_stream` INNER JOIN `activity_subscriptions` ON `activity_subscriptions`.`targetType` = `activity_stream`.`elementType` AND `activity_subscriptions`.`targetID` = `activity_stream`.`elementID` AND `activity_subscriptions`.`user` != `activity_stream`.`actor` WHERE `asid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
20
main.go
20
main.go
|
@ -36,15 +36,12 @@ var enable_websockets bool = false // Don't change this, the value is overwritte
|
|||
var startTime time.Time
|
||||
var timeLocation *time.Location
|
||||
var templates = template.New("")
|
||||
var no_css_tmpl = template.CSS("")
|
||||
var staff_css_tmpl = template.CSS(staff_css)
|
||||
var no_css_tmpl template.CSS = template.CSS("")
|
||||
var staff_css_tmpl template.CSS = template.CSS(staff_css)
|
||||
var settings map[string]interface{} = make(map[string]interface{})
|
||||
var external_sites map[string]string = make(map[string]string)
|
||||
var groups []Group
|
||||
var forums []Forum // The IDs for a forum tend to be low and sequential for the most part, so we can get more performance out of using a slice instead of a map AND it has better concurrency
|
||||
var forum_perms map[int]map[int]ForumPerms // [gid][fid]Perms
|
||||
var fstore ForumStore // :soon:
|
||||
var groupCapCount, forumCapCount int
|
||||
var groupCapCount int
|
||||
var static_files map[string]SFile = make(map[string]SFile)
|
||||
|
||||
var template_topic_handle func(TopicPage,io.Writer) = nil
|
||||
|
@ -62,6 +59,9 @@ func compile_templates() {
|
|||
NoticeList:[]string{"test"},
|
||||
Stylesheets:[]string{"panel"},
|
||||
Scripts:[]string{"whatever"},
|
||||
Sidebars:HeaderSidebars{
|
||||
Left: template.HTML("lalala"),
|
||||
},
|
||||
}
|
||||
|
||||
log.Print("Compiling the templates")
|
||||
|
@ -209,6 +209,13 @@ func main(){
|
|||
hooks["rrow_assign"] = nil
|
||||
init_plugins()
|
||||
|
||||
log.Print("Initialising the widgets")
|
||||
err = init_widgets()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Initialising the router")
|
||||
router := NewGenRouter(http.FileServer(http.Dir("./uploads")))
|
||||
///router.HandleFunc("/static/", route_static)
|
||||
///router.HandleFunc("/overview/", route_overview)
|
||||
|
@ -300,6 +307,7 @@ func main(){
|
|||
// pprof.StopCPUProfile()
|
||||
//}
|
||||
|
||||
log.Print("Initialising the HTTP server")
|
||||
if !enable_ssl {
|
||||
if server_port == "" {
|
||||
server_port = "80"
|
||||
|
|
20
mysql.go
20
mysql.go
|
@ -3,15 +3,12 @@
|
|||
package main
|
||||
|
||||
import "log"
|
||||
import "strings"
|
||||
import "database/sql"
|
||||
import _ "github.com/go-sql-driver/mysql"
|
||||
import "./query_gen/lib"
|
||||
|
||||
var notify_watchers_stmt *sql.Stmt
|
||||
var get_activity_feed_by_watcher_stmt *sql.Stmt
|
||||
var get_activity_count_by_watcher_stmt *sql.Stmt
|
||||
var add_forum_perms_to_forum_admins_stmt *sql.Stmt
|
||||
var add_forum_perms_to_forum_staff_stmt *sql.Stmt
|
||||
var add_forum_perms_to_forum_members_stmt *sql.Stmt
|
||||
var update_forum_perms_for_group_stmt *sql.Stmt
|
||||
|
@ -56,12 +53,6 @@ func _init_database() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing notify_watchers statement.")
|
||||
notify_watchers_stmt, err = db.Prepare("INSERT INTO activity_stream_matches(watcher, asid) SELECT activity_subscriptions.user, activity_stream.asid FROM activity_stream INNER JOIN activity_subscriptions ON activity_subscriptions.targetType = activity_stream.elementType and activity_subscriptions.targetID = activity_stream.elementID and activity_subscriptions.user != activity_stream.actor where asid = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing get_activity_feed_by_watcher statement.")
|
||||
get_activity_feed_by_watcher_stmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ? ORDER BY activity_stream.asid ASC LIMIT 8")
|
||||
if err != nil {
|
||||
|
@ -74,12 +65,6 @@ func _init_database() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing add_forum_perms_to_forum_admins statement.")
|
||||
add_forum_perms_to_forum_admins_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) SELECT `gid`,? AS fid,? AS preset,? AS permissions FROM users_groups WHERE is_admin = 1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing add_forum_perms_to_forum_staff statement.")
|
||||
add_forum_perms_to_forum_staff_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) SELECT `gid`,? AS fid,? AS preset,? AS permissions FROM users_groups WHERE is_admin = 0 AND is_mod = 1")
|
||||
if err != nil {
|
||||
|
@ -118,8 +103,3 @@ func _init_database() (err error) {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Temporary hack so that we can move all the raw queries out of the other files and into here
|
||||
func topic_list_query(visible_fids []string) string {
|
||||
return "select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, topics.postCount, topics.likeCount, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid where parentID in("+strings.Join(visible_fids,",")+") order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC"
|
||||
}
|
||||
|
|
|
@ -174,6 +174,15 @@ CREATE TABLE `themes`(
|
|||
unique(`uname`)
|
||||
);
|
||||
|
||||
CREATE TABLE `widgets`(
|
||||
`position` int not null,
|
||||
`side` varchar(100) not null,
|
||||
`type` varchar(100) not null,
|
||||
`active` tinyint(1) DEFAULT 0 not null,
|
||||
`location` varchar(100) not null,
|
||||
`data` text DEFAULT '' not null
|
||||
);
|
||||
|
||||
CREATE TABLE `moderation_logs`(
|
||||
`action` varchar(100) not null,
|
||||
`elementID` int not null,
|
||||
|
|
7
pages.go
7
pages.go
|
@ -13,6 +13,13 @@ type HeaderVars struct
|
|||
NoticeList []string
|
||||
Scripts []string
|
||||
Stylesheets []string
|
||||
Sidebars HeaderSidebars
|
||||
}
|
||||
|
||||
type HeaderSidebars struct
|
||||
{
|
||||
Left template.HTML
|
||||
Right template.HTML
|
||||
}
|
||||
|
||||
type ExtData struct
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* WIP Under Construction */
|
||||
package qgen
|
||||
|
||||
//import "fmt"
|
||||
import "database/sql"
|
||||
|
||||
var Builder *builder
|
||||
|
@ -36,6 +38,24 @@ func (build *builder) SimpleSelect(table string, columns string, where string, o
|
|||
return build.conn.Prepare(res)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleLeftJoin(table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleLeftJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
//fmt.Println("res",res)
|
||||
return build.conn.Prepare(res)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInnerJoin(table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
//fmt.Println("res",res)
|
||||
return build.conn.Prepare(res)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsert(table string, columns string, fields string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsert("_builder", table, columns, fields)
|
||||
if err != nil {
|
||||
|
|
|
@ -135,24 +135,23 @@ func (adapter *Mysql_Adapter) SimpleUpdate(name string, table string, set string
|
|||
// Remove the trailing comma
|
||||
querystr = querystr[0:len(querystr) - 1]
|
||||
|
||||
// Add support for BETWEEN x.x
|
||||
if len(where) != 0 {
|
||||
querystr += " WHERE"
|
||||
for _, loc := range _process_where(where) {
|
||||
var left, right string
|
||||
|
||||
if loc.LeftType == "column" {
|
||||
left = "`" + loc.LeftColumn + "`"
|
||||
} else {
|
||||
left = loc.LeftColumn
|
||||
for _, token := range loc.Expr {
|
||||
switch(token.Type) {
|
||||
case "function","operator","number","substitute":
|
||||
querystr += " " + token.Contents + ""
|
||||
case "column":
|
||||
querystr += " `" + token.Contents + "`"
|
||||
case "string":
|
||||
querystr += " '" + token.Contents + "'"
|
||||
default:
|
||||
panic("This token doesn't exist o_o")
|
||||
}
|
||||
|
||||
if loc.RightType == "column" {
|
||||
right = "`" + loc.RightColumn + "`"
|
||||
} else {
|
||||
right = loc.RightColumn
|
||||
}
|
||||
|
||||
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
|
||||
querystr += " AND"
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
}
|
||||
|
@ -173,22 +172,22 @@ func (adapter *Mysql_Adapter) SimpleDelete(name string, table string, where stri
|
|||
}
|
||||
|
||||
var querystr string = "DELETE FROM `" + table + "` WHERE"
|
||||
|
||||
// Add support for BETWEEN x.x
|
||||
for _, loc := range _process_where(where) {
|
||||
var left, right string
|
||||
|
||||
if loc.LeftType == "column" {
|
||||
left = "`" + loc.LeftColumn + "`"
|
||||
} else {
|
||||
left = loc.LeftColumn
|
||||
for _, token := range loc.Expr {
|
||||
switch(token.Type) {
|
||||
case "function","operator","number","substitute":
|
||||
querystr += " " + token.Contents + ""
|
||||
case "column":
|
||||
querystr += " `" + token.Contents + "`"
|
||||
case "string":
|
||||
querystr += " '" + token.Contents + "'"
|
||||
default:
|
||||
panic("This token doesn't exist o_o")
|
||||
}
|
||||
|
||||
if loc.RightType == "column" {
|
||||
right = "`" + loc.RightColumn + "`"
|
||||
} else {
|
||||
right = loc.RightColumn
|
||||
}
|
||||
|
||||
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
|
||||
querystr += " AND"
|
||||
}
|
||||
|
||||
querystr = strings.TrimSpace(querystr[0:len(querystr) - 4])
|
||||
|
@ -232,24 +231,24 @@ func (adapter *Mysql_Adapter) SimpleSelect(name string, table string, columns st
|
|||
querystr = querystr[0:len(querystr) - 1]
|
||||
|
||||
querystr += " FROM `" + table + "`"
|
||||
|
||||
// Add support for BETWEEN x.x
|
||||
if len(where) != 0 {
|
||||
querystr += " WHERE"
|
||||
for _, loc := range _process_where(where) {
|
||||
var left, right string
|
||||
|
||||
if loc.LeftType == "column" {
|
||||
left = "`" + loc.LeftColumn + "`"
|
||||
} else {
|
||||
left = loc.LeftColumn
|
||||
for _, token := range loc.Expr {
|
||||
switch(token.Type) {
|
||||
case "function","operator","number","substitute":
|
||||
querystr += " " + token.Contents + ""
|
||||
case "column":
|
||||
querystr += " `" + token.Contents + "`"
|
||||
case "string":
|
||||
querystr += " '" + token.Contents + "'"
|
||||
default:
|
||||
panic("This token doesn't exist o_o")
|
||||
}
|
||||
|
||||
if loc.RightType == "column" {
|
||||
right = "`" + loc.RightColumn + "`"
|
||||
} else {
|
||||
right = loc.RightColumn
|
||||
}
|
||||
|
||||
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
|
||||
querystr += " AND"
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
}
|
||||
|
@ -318,28 +317,28 @@ func (adapter *Mysql_Adapter) SimpleLeftJoin(name string, table1 string, table2
|
|||
// Remove the trailing AND
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
|
||||
// Add support for BETWEEN x.x
|
||||
if len(where) != 0 {
|
||||
querystr += " WHERE"
|
||||
for _, loc := range _process_where(where) {
|
||||
var left, right string
|
||||
|
||||
if loc.LeftTable != "" {
|
||||
left = "`" + loc.LeftTable + "`.`" + loc.LeftColumn + "`"
|
||||
} else if loc.LeftType == "column" {
|
||||
left = "`" + loc.LeftColumn + "`"
|
||||
for _, token := range loc.Expr {
|
||||
switch(token.Type) {
|
||||
case "function","operator","number","substitute":
|
||||
querystr += " " + token.Contents + ""
|
||||
case "column":
|
||||
halves := strings.Split(token.Contents,".")
|
||||
if len(halves) == 2 {
|
||||
querystr += " `" + halves[0] + "`.`" + halves[1] + "`"
|
||||
} else {
|
||||
left = loc.LeftColumn
|
||||
querystr += " `" + token.Contents + "`"
|
||||
}
|
||||
|
||||
if loc.RightTable != "" {
|
||||
right = "`" + loc.RightTable + "`.`" + loc.RightColumn + "`"
|
||||
} else if loc.RightType == "column" {
|
||||
right = "`" + loc.RightColumn + "`"
|
||||
} else {
|
||||
right = loc.RightColumn
|
||||
case "string":
|
||||
querystr += " '" + token.Contents + "'"
|
||||
default:
|
||||
panic("This token doesn't exist o_o")
|
||||
}
|
||||
|
||||
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
|
||||
}
|
||||
querystr += " AND"
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
}
|
||||
|
@ -408,28 +407,28 @@ func (adapter *Mysql_Adapter) SimpleInnerJoin(name string, table1 string, table2
|
|||
// Remove the trailing AND
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
|
||||
// Add support for BETWEEN x.x
|
||||
if len(where) != 0 {
|
||||
querystr += " WHERE"
|
||||
for _, loc := range _process_where(where) {
|
||||
var left, right string
|
||||
|
||||
if loc.LeftTable != "" {
|
||||
left = "`" + loc.LeftTable + "`.`" + loc.LeftColumn + "`"
|
||||
} else if loc.LeftType == "column" {
|
||||
left = "`" + loc.LeftColumn + "`"
|
||||
for _, token := range loc.Expr {
|
||||
switch(token.Type) {
|
||||
case "function","operator","number","substitute":
|
||||
querystr += " " + token.Contents + ""
|
||||
case "column":
|
||||
halves := strings.Split(token.Contents,".")
|
||||
if len(halves) == 2 {
|
||||
querystr += " `" + halves[0] + "`.`" + halves[1] + "`"
|
||||
} else {
|
||||
left = loc.LeftColumn
|
||||
querystr += " `" + token.Contents + "`"
|
||||
}
|
||||
|
||||
if loc.RightTable != "" {
|
||||
right = "`" + loc.RightTable + "`.`" + loc.RightColumn + "`"
|
||||
} else if loc.RightType == "column" {
|
||||
right = "`" + loc.RightColumn + "`"
|
||||
} else {
|
||||
right = loc.RightColumn
|
||||
case "string":
|
||||
querystr += " '" + token.Contents + "'"
|
||||
default:
|
||||
panic("This token doesn't exist o_o")
|
||||
}
|
||||
|
||||
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
|
||||
}
|
||||
querystr += " AND"
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
}
|
||||
|
@ -451,6 +450,163 @@ func (adapter *Mysql_Adapter) SimpleInnerJoin(name string, table1 string, table2
|
|||
return querystr, nil
|
||||
}
|
||||
|
||||
func (adapter *Mysql_Adapter) SimpleInsertSelect(name string, ins DB_Insert, sel DB_Select) (string, error) {
|
||||
/* Insert Portion */
|
||||
var querystr string = "INSERT INTO `" + ins.Table + "`("
|
||||
|
||||
// Escape the column names, just in case we've used a reserved keyword
|
||||
for _, column := range _process_columns(ins.Columns) {
|
||||
if column.Type == "function" {
|
||||
querystr += column.Left + ","
|
||||
} else {
|
||||
querystr += "`" + column.Left + "`,"
|
||||
}
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 1] + ") SELECT"
|
||||
|
||||
/* Select Portion */
|
||||
|
||||
for _, column := range _process_columns(sel.Columns) {
|
||||
var source, alias string
|
||||
|
||||
// Escape the column names, just in case we've used a reserved keyword
|
||||
if column.Type == "function" || column.Type == "substitute" {
|
||||
source = column.Left
|
||||
} else {
|
||||
source = "`" + column.Left + "`"
|
||||
}
|
||||
|
||||
if column.Alias != "" {
|
||||
alias = " AS `" + column.Alias + "`"
|
||||
}
|
||||
querystr += " " + source + alias + ","
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 1]
|
||||
|
||||
querystr += " FROM `" + sel.Table + "`"
|
||||
|
||||
// Add support for BETWEEN x.x
|
||||
if len(sel.Where) != 0 {
|
||||
querystr += " WHERE"
|
||||
for _, loc := range _process_where(sel.Where) {
|
||||
for _, token := range loc.Expr {
|
||||
switch(token.Type) {
|
||||
case "function","operator","number","substitute":
|
||||
querystr += " " + token.Contents + ""
|
||||
case "column":
|
||||
querystr += " `" + token.Contents + "`"
|
||||
case "string":
|
||||
querystr += " '" + token.Contents + "'"
|
||||
default:
|
||||
panic("This token doesn't exist o_o")
|
||||
}
|
||||
}
|
||||
querystr += " AND"
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
}
|
||||
|
||||
if len(sel.Orderby) != 0 {
|
||||
querystr += " ORDER BY "
|
||||
for _, column := range _process_orderby(sel.Orderby) {
|
||||
querystr += column.Column + " " + strings.ToUpper(column.Order) + ","
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 1]
|
||||
}
|
||||
|
||||
if sel.Limit != "" {
|
||||
querystr += " LIMIT " + sel.Limit
|
||||
}
|
||||
|
||||
querystr = strings.TrimSpace(querystr)
|
||||
adapter.push_statement(name,querystr)
|
||||
return querystr, nil
|
||||
}
|
||||
|
||||
func (adapter *Mysql_Adapter) SimpleInsertInnerJoin(name string, ins DB_Insert, sel DB_Join) (string, error) {
|
||||
/* Insert Portion */
|
||||
var querystr string = "INSERT INTO `" + ins.Table + "`("
|
||||
|
||||
// Escape the column names, just in case we've used a reserved keyword
|
||||
for _, column := range _process_columns(ins.Columns) {
|
||||
if column.Type == "function" {
|
||||
querystr += column.Left + ","
|
||||
} else {
|
||||
querystr += "`" + column.Left + "`,"
|
||||
}
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 1] + ") SELECT"
|
||||
|
||||
/* Select Portion */
|
||||
|
||||
for _, column := range _process_columns(sel.Columns) {
|
||||
var source, alias string
|
||||
|
||||
// Escape the column names, just in case we've used a reserved keyword
|
||||
if column.Table != "" {
|
||||
source = "`" + column.Table + "`.`" + column.Left + "`"
|
||||
} else if column.Type == "function" {
|
||||
source = column.Left
|
||||
} else {
|
||||
source = "`" + column.Left + "`"
|
||||
}
|
||||
|
||||
if column.Alias != "" {
|
||||
alias = " AS `" + column.Alias + "`"
|
||||
}
|
||||
querystr += " " + source + alias + ","
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 1]
|
||||
|
||||
querystr += " FROM `" + sel.Table1 + "` INNER JOIN `" + sel.Table2 + "` ON "
|
||||
for _, joiner := range _process_joiner(sel.Joiners) {
|
||||
querystr += "`" + joiner.LeftTable + "`.`" + joiner.LeftColumn + "` " + joiner.Operator + " `" + joiner.RightTable + "`.`" + joiner.RightColumn + "` AND "
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
|
||||
// Add support for BETWEEN x.x
|
||||
if len(sel.Where) != 0 {
|
||||
querystr += " WHERE"
|
||||
for _, loc := range _process_where(sel.Where) {
|
||||
for _, token := range loc.Expr {
|
||||
switch(token.Type) {
|
||||
case "function","operator","number","substitute":
|
||||
querystr += " " + token.Contents + ""
|
||||
case "column":
|
||||
halves := strings.Split(token.Contents,".")
|
||||
if len(halves) == 2 {
|
||||
querystr += " `" + halves[0] + "`.`" + halves[1] + "`"
|
||||
} else {
|
||||
querystr += " `" + token.Contents + "`"
|
||||
}
|
||||
case "string":
|
||||
querystr += " '" + token.Contents + "'"
|
||||
default:
|
||||
panic("This token doesn't exist o_o")
|
||||
}
|
||||
}
|
||||
querystr += " AND"
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
}
|
||||
|
||||
if len(sel.Orderby) != 0 {
|
||||
querystr += " ORDER BY "
|
||||
for _, column := range _process_orderby(sel.Orderby) {
|
||||
querystr += column.Column + " " + strings.ToUpper(column.Order) + ","
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 1]
|
||||
}
|
||||
|
||||
if sel.Limit != "" {
|
||||
querystr += " LIMIT " + sel.Limit
|
||||
}
|
||||
|
||||
querystr = strings.TrimSpace(querystr)
|
||||
adapter.push_statement(name,querystr)
|
||||
return querystr, nil
|
||||
}
|
||||
|
||||
func (adapter *Mysql_Adapter) SimpleCount(name string, table string, where string, limit string) (string, error) {
|
||||
if name == "" {
|
||||
return "", errors.New("You need a name for this statement")
|
||||
|
@ -460,24 +616,27 @@ func (adapter *Mysql_Adapter) SimpleCount(name string, table string, where strin
|
|||
}
|
||||
|
||||
var querystr string = "SELECT COUNT(*) AS `count` FROM `" + table + "`"
|
||||
|
||||
// Add support for BETWEEN x.x
|
||||
if len(where) != 0 {
|
||||
querystr += " WHERE"
|
||||
//fmt.Println("SimpleCount:",name)
|
||||
//fmt.Println("where:",where)
|
||||
//fmt.Println("_process_where:",_process_where(where))
|
||||
for _, loc := range _process_where(where) {
|
||||
var left, right string
|
||||
|
||||
if loc.LeftType == "column" {
|
||||
left = "`" + loc.LeftColumn + "`"
|
||||
} else {
|
||||
left = loc.LeftColumn
|
||||
for _, token := range loc.Expr {
|
||||
switch(token.Type) {
|
||||
case "function","operator","number","substitute":
|
||||
querystr += " " + token.Contents + ""
|
||||
case "column":
|
||||
querystr += " `" + token.Contents + "`"
|
||||
case "string":
|
||||
querystr += " '" + token.Contents + "'"
|
||||
default:
|
||||
panic("This token doesn't exist o_o")
|
||||
}
|
||||
|
||||
if loc.RightType == "column" {
|
||||
right = "`" + loc.RightColumn + "`"
|
||||
} else {
|
||||
right = loc.RightColumn
|
||||
}
|
||||
|
||||
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
|
||||
querystr += " AND"
|
||||
}
|
||||
querystr = querystr[0:len(querystr) - 4]
|
||||
}
|
||||
|
|
|
@ -6,6 +6,51 @@ import "errors"
|
|||
var DB_Registry []DB_Adapter
|
||||
var No_Adapter = errors.New("This adapter doesn't exist")
|
||||
|
||||
type DB_Select struct
|
||||
{
|
||||
Table string
|
||||
Columns string
|
||||
Where string
|
||||
Orderby string
|
||||
Limit string
|
||||
}
|
||||
|
||||
type DB_Join struct
|
||||
{
|
||||
Table1 string
|
||||
Table2 string
|
||||
Columns string
|
||||
Joiners string
|
||||
Where string
|
||||
Orderby string
|
||||
Limit string
|
||||
}
|
||||
|
||||
type DB_Insert struct
|
||||
{
|
||||
Table string
|
||||
Columns string
|
||||
Fields string
|
||||
}
|
||||
|
||||
/*type DB_Select struct
|
||||
{
|
||||
Name string
|
||||
Table string
|
||||
Columns []DB_Column
|
||||
Where []DB_Where
|
||||
Orderby []DB_Order
|
||||
Limit DB_Limit
|
||||
}
|
||||
|
||||
type DB_Insert struct
|
||||
{
|
||||
Name string
|
||||
Table string
|
||||
Columns []DB_Column
|
||||
Fields []DB_Field
|
||||
}*/
|
||||
|
||||
type DB_Column struct
|
||||
{
|
||||
Table string
|
||||
|
@ -22,13 +67,7 @@ type DB_Field struct
|
|||
|
||||
type DB_Where struct
|
||||
{
|
||||
LeftTable string
|
||||
LeftColumn string
|
||||
RightTable string
|
||||
RightColumn string
|
||||
Operator string
|
||||
LeftType string
|
||||
RightType string
|
||||
Expr []DB_Token // Simple expressions, the innards of functions are opaque for now.
|
||||
}
|
||||
|
||||
type DB_Joiner struct
|
||||
|
@ -71,6 +110,8 @@ type DB_Adapter interface {
|
|||
SimpleSelect(string,string,string,string,string,string) (string, error)
|
||||
SimpleLeftJoin(string,string,string,string,string,string,string,string) (string, error)
|
||||
SimpleInnerJoin(string,string,string,string,string,string,string,string) (string, error)
|
||||
SimpleInsertSelect(string,DB_Insert,DB_Select) (string,error)
|
||||
SimpleInsertInnerJoin(string,DB_Insert,DB_Join) (string,error)
|
||||
SimpleCount(string,string,string,string) (string, error)
|
||||
Write() error
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ func _process_columns(colstr string) (columns []DB_Column) {
|
|||
}
|
||||
if halves[0][len(halves[0]) - 1] == ')' {
|
||||
outcol.Type = "function"
|
||||
} else if halves[0] == "?" {
|
||||
outcol.Type = "substitute"
|
||||
} else {
|
||||
outcol.Type = "column"
|
||||
}
|
||||
|
@ -83,42 +85,97 @@ func _process_joiner(joinstr string) (joiner []DB_Joiner) {
|
|||
return joiner
|
||||
}
|
||||
|
||||
// TO-DO: Add support for keywords like BETWEEN. We'll probably need an arbitrary expression parser like with the update setters.
|
||||
func _process_where(wherestr string) (where []DB_Where) {
|
||||
if wherestr == "" {
|
||||
return where
|
||||
}
|
||||
wherestr = strings.Replace(wherestr," and "," AND ",-1)
|
||||
|
||||
var buffer string
|
||||
var optype int // 0: None, 1: Number, 2: Column, 3: Function, 4: String, 5: Operator
|
||||
for _, segment := range strings.Split(wherestr," AND ") {
|
||||
// TO-DO: Subparse the contents of a function and spit out a DB_Function struct
|
||||
var outwhere DB_Where
|
||||
var parseOffset int
|
||||
var left, right string
|
||||
|
||||
left, parseOffset = _get_identifier(segment, parseOffset)
|
||||
outwhere.Operator, parseOffset = _get_operator(segment, parseOffset + 1)
|
||||
right, parseOffset = _get_identifier(segment, parseOffset + 1)
|
||||
outwhere.LeftType = _get_identifier_type(left)
|
||||
outwhere.RightType = _get_identifier_type(right)
|
||||
|
||||
left_operand := strings.Split(left,".")
|
||||
right_operand := strings.Split(right,".")
|
||||
|
||||
if len(left_operand) == 2 {
|
||||
outwhere.LeftTable = strings.TrimSpace(left_operand[0])
|
||||
outwhere.LeftColumn = strings.TrimSpace(left_operand[1])
|
||||
} else {
|
||||
outwhere.LeftColumn = strings.TrimSpace(left_operand[0])
|
||||
var tmp_where DB_Where
|
||||
segment += ")"
|
||||
for i := 0; i < len(segment); i++ {
|
||||
char := segment[i]
|
||||
//fmt.Println("optype",optype)
|
||||
switch(optype) {
|
||||
case 0: // unknown
|
||||
//fmt.Println("case 0:",char,string(char))
|
||||
if ('0' <= char && char <= '9') {
|
||||
optype = 1
|
||||
buffer = string(char)
|
||||
} else if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' {
|
||||
optype = 2
|
||||
buffer = string(char)
|
||||
} else if char == '\'' {
|
||||
optype = 4
|
||||
buffer = ""
|
||||
} else if _is_op_byte(char) {
|
||||
optype = 5
|
||||
buffer = string(char)
|
||||
} else if char == '?' {
|
||||
//fmt.Println("Expr:","?")
|
||||
tmp_where.Expr = append(tmp_where.Expr,DB_Token{"?","substitute"})
|
||||
}
|
||||
|
||||
if len(right_operand) == 2 {
|
||||
outwhere.RightTable = strings.TrimSpace(right_operand[0])
|
||||
outwhere.RightColumn = strings.TrimSpace(right_operand[1])
|
||||
case 1: // number
|
||||
if ('0' <= char && char <= '9') {
|
||||
buffer += string(char)
|
||||
} else {
|
||||
outwhere.RightColumn = strings.TrimSpace(right_operand[0])
|
||||
optype = 0
|
||||
i--
|
||||
//fmt.Println("Expr:",buffer)
|
||||
tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"number"})
|
||||
}
|
||||
|
||||
where = append(where,outwhere)
|
||||
case 2: // column
|
||||
if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '.' || char == '_' {
|
||||
buffer += string(char)
|
||||
} else if char == '(' {
|
||||
optype = 3
|
||||
i--
|
||||
} else {
|
||||
optype = 0
|
||||
i--
|
||||
//fmt.Println("Expr:",buffer)
|
||||
tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"column"})
|
||||
}
|
||||
case 3: // function
|
||||
var pre_i int = i
|
||||
//fmt.Println("buffer",buffer)
|
||||
//fmt.Println("len(halves)",len(halves[1]))
|
||||
//fmt.Println("pre_i",string(halves[1][pre_i]))
|
||||
//fmt.Println("msg prior to pre_i",halves[1][0:pre_i])
|
||||
i = _skip_function_call(segment,i-1)
|
||||
//fmt.Println("i",i)
|
||||
//fmt.Println("msg prior to i-1",halves[1][0:i-1])
|
||||
//fmt.Println("string(i-1)",string(halves[1][i-1]))
|
||||
//fmt.Println("string(i)",string(halves[1][i]))
|
||||
buffer += segment[pre_i:i] + string(segment[i])
|
||||
//fmt.Println("Expr:",buffer)
|
||||
tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"function"})
|
||||
optype = 0
|
||||
case 4: // string
|
||||
if char != '\'' {
|
||||
buffer += string(char)
|
||||
} else {
|
||||
optype = 0
|
||||
//fmt.Println("Expr:",buffer)
|
||||
tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"string"})
|
||||
}
|
||||
case 5: // operator
|
||||
if _is_op_byte(char) {
|
||||
buffer += string(char)
|
||||
} else {
|
||||
optype = 0
|
||||
i--
|
||||
//fmt.Println("Expr:",buffer)
|
||||
tmp_where.Expr = append(tmp_where.Expr,DB_Token{buffer,"operator"})
|
||||
}
|
||||
default:
|
||||
panic("Bad optype in _process_where")
|
||||
}
|
||||
}
|
||||
where = append(where,tmp_where)
|
||||
}
|
||||
return where
|
||||
}
|
||||
|
@ -170,11 +227,12 @@ func _process_set(setstr string) (setter []DB_Setter) {
|
|||
if ('0' <= char && char <= '9') {
|
||||
optype = 1
|
||||
buffer = string(char)
|
||||
} else if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') {
|
||||
} else if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' {
|
||||
optype = 2
|
||||
buffer = string(char)
|
||||
} else if char == '\'' {
|
||||
optype = 4
|
||||
buffer = ""
|
||||
} else if _is_op_byte(char) {
|
||||
optype = 5
|
||||
buffer = string(char)
|
||||
|
@ -192,7 +250,7 @@ func _process_set(setstr string) (setter []DB_Setter) {
|
|||
tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"number"})
|
||||
}
|
||||
case 2: // column
|
||||
if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') {
|
||||
if ('a' <= char && char <= 'z') || ('A' <= char && char <= 'Z') || char == '_' {
|
||||
buffer += string(char)
|
||||
} else if char == '(' {
|
||||
optype = 3
|
||||
|
@ -235,6 +293,8 @@ func _process_set(setstr string) (setter []DB_Setter) {
|
|||
//fmt.Println("Expr:",buffer)
|
||||
tmp_setter.Expr = append(tmp_setter.Expr,DB_Token{buffer,"operator"})
|
||||
}
|
||||
default:
|
||||
panic("Bad optype in _process_set")
|
||||
}
|
||||
}
|
||||
setter = append(setter,tmp_setter)
|
||||
|
@ -258,6 +318,10 @@ func _is_op_byte(char byte) bool {
|
|||
return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/'
|
||||
}
|
||||
|
||||
func _is_op_rune(char rune) bool {
|
||||
return char == '<' || char == '>' || char == '=' || char == '!' || char == '*' || char == '%' || char == '+' || char == '-' || char == '/'
|
||||
}
|
||||
|
||||
func _process_fields(fieldstr string) (fields []DB_Field) {
|
||||
if fieldstr == "" {
|
||||
return fields
|
||||
|
|
|
@ -18,34 +18,57 @@ func write_statements(adapter qgen.DB_Adapter) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_left_joins(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_inner_joins(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_inserts(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_replaces(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_updates(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_deletes(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_simple_counts(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_insert_selects(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_insert_left_joins(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = write_insert_inner_joins(adapter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -84,6 +107,8 @@ func write_selects(adapter qgen.DB_Adapter) error {
|
|||
|
||||
adapter.SimpleSelect("get_themes","themes","uname, default","","","")
|
||||
|
||||
adapter.SimpleSelect("get_widgets","widgets","position, side, type, active, location, data","","position ASC","")
|
||||
|
||||
adapter.SimpleSelect("is_plugin_active","plugins","active","uname = ?","","")
|
||||
|
||||
adapter.SimpleSelect("get_users","users","uid, name, group, active, is_super_admin, avatar","","","")
|
||||
|
@ -291,7 +316,29 @@ func write_deletes(adapter qgen.DB_Adapter) error {
|
|||
}
|
||||
|
||||
func write_simple_counts(adapter qgen.DB_Adapter) error {
|
||||
adapter.SimpleCount("report_exists","topics","data = ? and data != '' and parentID = 1","")
|
||||
adapter.SimpleCount("report_exists","topics","data = ? AND data != '' AND parentID = 1","")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func write_insert_selects(adapter qgen.DB_Adapter) error {
|
||||
adapter.SimpleInsertSelect("add_forum_perms_to_forum_admins",
|
||||
qgen.DB_Insert{"forums_permissions","gid,fid,preset,permissions",""},
|
||||
qgen.DB_Select{"users_groups","gid, ? AS fid, ? AS preset, ? AS permissions","is_admin = 1","",""},
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func write_insert_left_joins(adapter qgen.DB_Adapter) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func write_insert_inner_joins(adapter qgen.DB_Adapter) error {
|
||||
adapter.SimpleInsertInnerJoin("notify_watchers",
|
||||
qgen.DB_Insert{"activity_stream_matches","watcher, asid",""},
|
||||
qgen.DB_Join{"activity_stream","activity_subscriptions","activity_subscriptions.user, activity_stream.asid","activity_subscriptions.targetType = activity_stream.elementType AND activity_subscriptions.targetID = activity_stream.elementID AND activity_subscriptions.user != activity_stream.actor","asid = ?","",""},
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
35
routes.go
35
routes.go
|
@ -16,6 +16,8 @@ import (
|
|||
"html"
|
||||
"html/template"
|
||||
"database/sql"
|
||||
|
||||
"./query_gen/lib"
|
||||
)
|
||||
|
||||
import _ "github.com/go-sql-driver/mysql"
|
||||
|
@ -104,16 +106,25 @@ func route_topics(w http.ResponseWriter, r *http.Request){
|
|||
return
|
||||
}
|
||||
|
||||
var fidList []string
|
||||
var qlist string
|
||||
var fidList []interface{}
|
||||
group := groups[user.Group]
|
||||
for _, fid := range group.CanSee {
|
||||
if forums[fid].Name != "" {
|
||||
fidList = append(fidList,strconv.Itoa(fid))
|
||||
qlist += "?,"
|
||||
}
|
||||
}
|
||||
qlist = qlist[0:len(qlist) - 1]
|
||||
|
||||
var topicList []TopicsRow
|
||||
rows, err := db.Query(topic_list_query(fidList))
|
||||
stmt, err := qgen.Builder.SimpleLeftJoin("topics","users","topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, topics.postCount, topics.likeCount, users.name, users.avatar","topics.createdBy = users.uid","parentID IN("+qlist+")","topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC","")
|
||||
if err != nil {
|
||||
InternalError(err,w,r)
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := stmt.Query(fidList...)
|
||||
if err != nil {
|
||||
InternalError(err,w,r)
|
||||
return
|
||||
|
@ -166,9 +177,9 @@ func route_topics(w http.ResponseWriter, r *http.Request){
|
|||
if template_topics_handle != nil {
|
||||
template_topics_handle(pi,w)
|
||||
} else {
|
||||
mapping, ok := themes[defaultTheme].TemplatesMap["topic"]
|
||||
mapping, ok := themes[defaultTheme].TemplatesMap["topics"]
|
||||
if !ok {
|
||||
mapping = "topic"
|
||||
mapping = "topics"
|
||||
}
|
||||
err = templates.ExecuteTemplate(w,mapping + ".html", pi)
|
||||
if err != nil {
|
||||
|
@ -1689,8 +1700,20 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) {
|
|||
LocalError("You didn't put in a password.",w,r,user)
|
||||
return
|
||||
}
|
||||
if password == "test" || password == "123456" || password == "123" || password == "password" {
|
||||
LocalError("Your password is too weak.",w,r,user)
|
||||
|
||||
if password == username {
|
||||
LocalError("You can't use your username as your password.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
if password == email {
|
||||
LocalError("You can't use your email as your password.",w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
err = weak_password(password)
|
||||
if err != nil {
|
||||
LocalError(err.Error(),w,r,user)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -51,11 +51,15 @@ w.Write(menu_6)
|
|||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_9)
|
||||
if tmpl_forum_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(header_10)
|
||||
}
|
||||
w.Write(header_11)
|
||||
if len(tmpl_forum_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_forum_vars.Header.NoticeList {
|
||||
w.Write(header_10)
|
||||
w.Write(header_12)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_11)
|
||||
w.Write(header_13)
|
||||
}
|
||||
}
|
||||
if tmpl_forum_vars.Page > 1 {
|
||||
|
@ -133,4 +137,10 @@ w.Write(forum_31)
|
|||
}
|
||||
w.Write(forum_32)
|
||||
w.Write(footer_0)
|
||||
if tmpl_forum_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(string(tmpl_forum_vars.Header.Sidebars.Right)))
|
||||
w.Write(footer_2)
|
||||
}
|
||||
w.Write(footer_3)
|
||||
}
|
||||
|
|
|
@ -51,11 +51,15 @@ w.Write(menu_6)
|
|||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_9)
|
||||
if tmpl_forums_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(header_10)
|
||||
}
|
||||
w.Write(header_11)
|
||||
if len(tmpl_forums_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_forums_vars.Header.NoticeList {
|
||||
w.Write(header_10)
|
||||
w.Write(header_12)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_11)
|
||||
w.Write(header_13)
|
||||
}
|
||||
}
|
||||
w.Write(forums_0)
|
||||
|
@ -106,4 +110,10 @@ w.Write(forums_20)
|
|||
}
|
||||
w.Write(forums_21)
|
||||
w.Write(footer_0)
|
||||
if tmpl_forums_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(string(tmpl_forums_vars.Header.Sidebars.Right)))
|
||||
w.Write(footer_2)
|
||||
}
|
||||
w.Write(footer_3)
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ var header_1 []byte = []byte(`</title>
|
|||
`)
|
||||
var header_2 []byte = []byte(`
|
||||
<link href="/static/`)
|
||||
var header_3 []byte = []byte(`.css" rel="stylesheet" type="text/css">
|
||||
var header_3 []byte = []byte(`" rel="stylesheet" type="text/css">
|
||||
`)
|
||||
var header_4 []byte = []byte(`
|
||||
<script type="text/javascript" src="/static/jquery-3.1.1.min.js"></script>
|
||||
`)
|
||||
var header_5 []byte = []byte(`
|
||||
<script type="text/javascript" src="/static/`)
|
||||
var header_6 []byte = []byte(`.js"></script>
|
||||
var header_6 []byte = []byte(`"></script>
|
||||
`)
|
||||
var header_7 []byte = []byte(`
|
||||
<script type="text/javascript">var session = "`)
|
||||
|
@ -64,10 +64,12 @@ var menu_7 []byte = []byte(`
|
|||
</div>
|
||||
`)
|
||||
var header_9 []byte = []byte(`
|
||||
<div id="back"><div id="main">
|
||||
<div id="back"><div id="main" `)
|
||||
var header_10 []byte = []byte(`class="shrink_main"`)
|
||||
var header_11 []byte = []byte(`>
|
||||
`)
|
||||
var header_10 []byte = []byte(`<div class="alert">`)
|
||||
var header_11 []byte = []byte(`</div>`)
|
||||
var header_12 []byte = []byte(`<div class="alert">`)
|
||||
var header_13 []byte = []byte(`</div>`)
|
||||
var topic_0 []byte = []byte(`<div id="prevFloat" class="prev_button"><a class="prev_link" href="/topic/`)
|
||||
var topic_1 []byte = []byte(`?page=`)
|
||||
var topic_2 []byte = []byte(`"><</a></div>`)
|
||||
|
@ -226,7 +228,14 @@ var topic_83 []byte = []byte(`' type="hidden" />
|
|||
</form>
|
||||
</div>
|
||||
`)
|
||||
var footer_0 []byte = []byte(` </div><div style="clear: both;"></div></div></div>
|
||||
var footer_0 []byte = []byte(` </div>
|
||||
`)
|
||||
var footer_1 []byte = []byte(`<div class="sidebar">`)
|
||||
var footer_2 []byte = []byte(`</div>`)
|
||||
var footer_3 []byte = []byte(`
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
// +build !no_templategen
|
||||
package main
|
||||
import "strconv"
|
||||
import "io"
|
||||
import "strconv"
|
||||
|
||||
func init() {
|
||||
template_profile_handle = template_profile
|
||||
|
@ -51,11 +51,15 @@ w.Write(menu_6)
|
|||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_9)
|
||||
if tmpl_profile_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(header_10)
|
||||
}
|
||||
w.Write(header_11)
|
||||
if len(tmpl_profile_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_profile_vars.Header.NoticeList {
|
||||
w.Write(header_10)
|
||||
w.Write(header_12)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_11)
|
||||
w.Write(header_13)
|
||||
}
|
||||
}
|
||||
w.Write(profile_0)
|
||||
|
@ -139,4 +143,10 @@ w.Write(profile_37)
|
|||
}
|
||||
w.Write(profile_38)
|
||||
w.Write(footer_0)
|
||||
if tmpl_profile_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(string(tmpl_profile_vars.Header.Sidebars.Right)))
|
||||
w.Write(footer_2)
|
||||
}
|
||||
w.Write(footer_3)
|
||||
}
|
||||
|
|
|
@ -51,11 +51,15 @@ w.Write(menu_6)
|
|||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_9)
|
||||
if tmpl_topic_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(header_10)
|
||||
}
|
||||
w.Write(header_11)
|
||||
if len(tmpl_topic_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_topic_vars.Header.NoticeList {
|
||||
w.Write(header_10)
|
||||
w.Write(header_12)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_11)
|
||||
w.Write(header_13)
|
||||
}
|
||||
}
|
||||
if tmpl_topic_vars.Page > 1 {
|
||||
|
@ -247,4 +251,10 @@ w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
|||
w.Write(topic_83)
|
||||
}
|
||||
w.Write(footer_0)
|
||||
if tmpl_topic_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(string(tmpl_topic_vars.Header.Sidebars.Right)))
|
||||
w.Write(footer_2)
|
||||
}
|
||||
w.Write(footer_3)
|
||||
}
|
||||
|
|
|
@ -51,11 +51,15 @@ w.Write(menu_6)
|
|||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_9)
|
||||
if tmpl_topic_alt_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(header_10)
|
||||
}
|
||||
w.Write(header_11)
|
||||
if len(tmpl_topic_alt_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_topic_alt_vars.Header.NoticeList {
|
||||
w.Write(header_10)
|
||||
w.Write(header_12)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_11)
|
||||
w.Write(header_13)
|
||||
}
|
||||
}
|
||||
if tmpl_topic_alt_vars.Page > 1 {
|
||||
|
@ -253,4 +257,10 @@ w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
|||
w.Write(topic_alt_87)
|
||||
}
|
||||
w.Write(footer_0)
|
||||
if tmpl_topic_alt_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(string(tmpl_topic_alt_vars.Header.Sidebars.Right)))
|
||||
w.Write(footer_2)
|
||||
}
|
||||
w.Write(footer_3)
|
||||
}
|
||||
|
|
|
@ -51,11 +51,15 @@ w.Write(menu_6)
|
|||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_9)
|
||||
if tmpl_topics_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(header_10)
|
||||
}
|
||||
w.Write(header_11)
|
||||
if len(tmpl_topics_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_topics_vars.Header.NoticeList {
|
||||
w.Write(header_10)
|
||||
w.Write(header_12)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_11)
|
||||
w.Write(header_13)
|
||||
}
|
||||
}
|
||||
w.Write(topics_0)
|
||||
|
@ -109,4 +113,10 @@ w.Write(topics_21)
|
|||
}
|
||||
w.Write(topics_22)
|
||||
w.Write(footer_0)
|
||||
if tmpl_topics_vars.Header.Sidebars.Right != "" {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(string(tmpl_topics_vars.Header.Sidebars.Right)))
|
||||
w.Write(footer_2)
|
||||
}
|
||||
w.Write(footer_3)
|
||||
}
|
||||
|
|
10
templates.go
10
templates.go
|
@ -274,6 +274,9 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu
|
|||
out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}"
|
||||
}
|
||||
case reflect.Slice:
|
||||
if outVal.Len() == 0 {
|
||||
panic("The sample data needs at-least one or more elements for the slices. We're looking into removing this requirement at some point!")
|
||||
}
|
||||
item := outVal.Index(0)
|
||||
out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}"
|
||||
case reflect.Invalid:
|
||||
|
@ -323,7 +326,7 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
|
|||
fmt.Println("Field Node:",n.Ident)
|
||||
}
|
||||
|
||||
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
||||
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Variable declarations are coming soon! */
|
||||
cur := holdreflect
|
||||
|
||||
var varbit string
|
||||
|
@ -780,7 +783,6 @@ func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, templ
|
|||
fmt.Println("Variable Field!")
|
||||
fmt.Println(bit)
|
||||
}
|
||||
|
||||
if bit == "" {
|
||||
continue
|
||||
}
|
||||
|
@ -793,6 +795,10 @@ func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, templ
|
|||
out += "." + bit
|
||||
}
|
||||
|
||||
if !cur.IsValid() {
|
||||
panic(out + "^\n" + "Invalid value. Maybe, it doesn't exist?")
|
||||
}
|
||||
|
||||
if super_debug {
|
||||
fmt.Println("Data Kind:",cur.Kind())
|
||||
fmt.Println("Data Type:",cur.Type().Name())
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
</div><div style="clear: both;"></div></div></div>
|
||||
</div>
|
||||
{{if .Header.Sidebars.Right}}<div class="sidebar">{{.Header.Sidebars.Right}}</div>{{end}}
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
<title>{{.Title}}</title>
|
||||
<link href="/static/main.css" rel="stylesheet" type="text/css">
|
||||
{{range .Header.Stylesheets}}
|
||||
<link href="/static/{{.}}.css" rel="stylesheet" type="text/css">
|
||||
<link href="/static/{{.}}" rel="stylesheet" type="text/css">
|
||||
{{end}}
|
||||
<script type="text/javascript" src="/static/jquery-3.1.1.min.js"></script>
|
||||
{{range .Header.Scripts}}
|
||||
<script type="text/javascript" src="/static/{{.}}.js"></script>
|
||||
<script type="text/javascript" src="/static/{{.}}"></script>
|
||||
{{end}}
|
||||
<script type="text/javascript">var session = "{{.CurrentUser.Session}}";
|
||||
</script>
|
||||
|
@ -18,5 +18,5 @@
|
|||
<body>
|
||||
<div class="container">
|
||||
{{template "menu.html" .}}
|
||||
<div id="back"><div id="main">
|
||||
<div id="back"><div id="main" {{if .Header.Sidebars.Right}}class="shrink_main"{{end}}>
|
||||
{{range .Header.NoticeList}}<div class="alert">{{.}}</div>{{end}}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<div class="rowblock">
|
||||
<div class="rowitem">{{.Name}}</div>
|
||||
</div>
|
||||
<div class="rowblock">
|
||||
<div class="rowitem">{{.Text}}</div>
|
||||
</div>
|
10
themes.go
10
themes.go
|
@ -32,9 +32,11 @@ type Theme struct
|
|||
ForkOf string
|
||||
Tag string
|
||||
URL string
|
||||
Sidebars string // Allowed Values: left, right, both, false
|
||||
Settings map[string]ThemeSetting
|
||||
Templates []TemplateMapping
|
||||
TemplatesMap map[string]string // TO-DO: Make template mapping work without the template compiler
|
||||
TemplatesMap map[string]string
|
||||
Resources []ThemeResource
|
||||
|
||||
// This variable should only be set and unset by the system, not the theme meta file
|
||||
Active bool
|
||||
|
@ -53,6 +55,12 @@ type TemplateMapping struct
|
|||
//When string
|
||||
}
|
||||
|
||||
type ThemeResource struct
|
||||
{
|
||||
Name string
|
||||
Location string
|
||||
}
|
||||
|
||||
func LoadThemes() error {
|
||||
rows, err := get_themes_stmt.Query()
|
||||
if err != nil {
|
||||
|
|
|
@ -141,7 +141,9 @@ li a {
|
|||
padding: 0px;
|
||||
padding-top: 0px;
|
||||
}
|
||||
.rowblock:empty { display: none; }
|
||||
.rowblock:empty {
|
||||
display: none;
|
||||
}
|
||||
.rowsmall {
|
||||
font-size:12px;
|
||||
}
|
||||
|
@ -449,6 +451,18 @@ button.username { position: relative; top: -0.25px; }
|
|||
top: -2px;
|
||||
}
|
||||
|
||||
@media(min-width: 881px) {
|
||||
.shrink_main {
|
||||
float: left;
|
||||
width: calc(75% - 12px);
|
||||
}
|
||||
.sidebar {
|
||||
float: left;
|
||||
width: 25%;
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 880px) {
|
||||
li {
|
||||
height: 29px;
|
||||
|
@ -477,6 +491,7 @@ button.username { position: relative; top: -0.25px; }
|
|||
overflow-x: hidden;
|
||||
}
|
||||
.container { width: auto; }
|
||||
.sidebar { display: none; }
|
||||
.selectedAlert .alertList { top: 37px; right: 4px; }
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/* Sample CSS file injected by Tempra Simple. Doesn't do anything. */
|
|
@ -5,5 +5,12 @@
|
|||
"Creator": "Azareal",
|
||||
"FullImage": "tempra-simple.png",
|
||||
"MobileFriendly": true,
|
||||
"URL": "github.com/Azareal/Gosora"
|
||||
"URL": "github.com/Azareal/Gosora",
|
||||
"Sidebars":"false",
|
||||
"Resources": [
|
||||
{
|
||||
"Name": "sample.css",
|
||||
"Location": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
65
user.go
65
user.go
|
@ -2,9 +2,11 @@ package main
|
|||
|
||||
import (
|
||||
//"fmt"
|
||||
"strings"
|
||||
"strconv"
|
||||
"net"
|
||||
"net/http"
|
||||
"html/template"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"database/sql"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
|
@ -80,11 +82,12 @@ func SendValidationEmail(username string, email string, token string) bool {
|
|||
}
|
||||
|
||||
func SimpleForumSessionCheck(w http.ResponseWriter, r *http.Request, fid int) (user User, success bool) {
|
||||
user, success = SimpleSessionCheck(w,r)
|
||||
if !forum_exists(fid) {
|
||||
PreError("The target forum doesn't exist.",w,r)
|
||||
return user, false
|
||||
}
|
||||
user, success = SimpleSessionCheck(w,r)
|
||||
|
||||
fperms := groups[user.Group].Forums[fid]
|
||||
if fperms.Overrides && !user.Is_Super_Admin {
|
||||
user.Perms.ViewTopic = fperms.ViewTopic
|
||||
|
@ -108,11 +111,12 @@ func SimpleForumSessionCheck(w http.ResponseWriter, r *http.Request, fid int) (u
|
|||
}
|
||||
|
||||
func ForumSessionCheck(w http.ResponseWriter, r *http.Request, fid int) (user User, headerVars HeaderVars, success bool) {
|
||||
user, headerVars, success = SessionCheck(w,r)
|
||||
if !forum_exists(fid) {
|
||||
NotFound(w,r)
|
||||
return user, headerVars, false
|
||||
}
|
||||
user, success = SimpleSessionCheck(w,r)
|
||||
|
||||
fperms := groups[user.Group].Forums[fid]
|
||||
//fmt.Printf("%+v\n", user.Perms)
|
||||
//fmt.Printf("%+v\n", fperms)
|
||||
|
@ -134,9 +138,6 @@ func ForumSessionCheck(w http.ResponseWriter, r *http.Request, fid int) (user Us
|
|||
}
|
||||
}
|
||||
}
|
||||
if user.Is_Banned {
|
||||
headerVars.NoticeList = append(headerVars.NoticeList,"Your account has been suspended. Some of your permissions may have been revoked.")
|
||||
}
|
||||
return user, headerVars, success
|
||||
}
|
||||
|
||||
|
@ -147,7 +148,25 @@ func _panel_session_check(w http.ResponseWriter, r *http.Request) (user User, he
|
|||
NoPermissions(w,r,user)
|
||||
return user, headerVars, false
|
||||
}
|
||||
headerVars.Stylesheets = append(headerVars.Stylesheets,"panel")
|
||||
|
||||
headerVars.Stylesheets = append(headerVars.Stylesheets,"panel.css")
|
||||
if len(themes[defaultTheme].Resources) != 0 {
|
||||
rlist := themes[defaultTheme].Resources
|
||||
for _, resource := range rlist {
|
||||
if resource.Location == "global" || resource.Location == "panel" {
|
||||
halves := strings.Split(resource.Name,".")
|
||||
if len(halves) != 2 {
|
||||
continue
|
||||
}
|
||||
if halves[1] == "css" {
|
||||
headerVars.Stylesheets = append(headerVars.Stylesheets,resource.Name)
|
||||
} else if halves[1] == "js" {
|
||||
headerVars.Scripts = append(headerVars.Scripts,resource.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return user, headerVars, success
|
||||
}
|
||||
func _simple_panel_session_check(w http.ResponseWriter, r *http.Request) (user User, success bool) {
|
||||
|
@ -164,6 +183,40 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, headerVars
|
|||
if user.Is_Banned {
|
||||
headerVars.NoticeList = append(headerVars.NoticeList,"Your account has been suspended. Some of your permissions may have been revoked.")
|
||||
}
|
||||
|
||||
if len(themes[defaultTheme].Resources) != 0 {
|
||||
rlist := themes[defaultTheme].Resources
|
||||
for _, resource := range rlist {
|
||||
if resource.Location == "global" || resource.Location == "frontend" {
|
||||
halves := strings.Split(resource.Name,".")
|
||||
if len(halves) != 2 {
|
||||
continue
|
||||
}
|
||||
if halves[1] == "css" {
|
||||
headerVars.Stylesheets = append(headerVars.Stylesheets,resource.Name)
|
||||
} else if halves[1] == "js" {
|
||||
headerVars.Scripts = append(headerVars.Scripts,resource.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TO-DO: Support for left sidebars and sidebars on both sides
|
||||
//fmt.Println("themes[defaultTheme].Sidebars",themes[defaultTheme].Sidebars)
|
||||
if themes[defaultTheme].Sidebars == "right" {
|
||||
if len(docks.RightSidebar) != 0 {
|
||||
var sbody string
|
||||
for _, widget := range docks.RightSidebar {
|
||||
//fmt.Println("widget",widget)
|
||||
if widget.Enabled && widget.Location == "global" {
|
||||
sbody += widget.Body
|
||||
//fmt.Println("sbody",sbody)
|
||||
}
|
||||
}
|
||||
headerVars.Sidebars.Right = template.HTML(sbody)
|
||||
}
|
||||
}
|
||||
|
||||
return user, headerVars, success
|
||||
}
|
||||
|
||||
|
|
52
utils.go
52
utils.go
|
@ -5,6 +5,7 @@ import (
|
|||
"time"
|
||||
"os"
|
||||
"math"
|
||||
"errors"
|
||||
"strings"
|
||||
"unicode"
|
||||
"strconv"
|
||||
|
@ -171,6 +172,57 @@ func SendEmail(email string, subject string, msg string) (res bool) {
|
|||
return true
|
||||
}
|
||||
|
||||
func weak_password(password string) error {
|
||||
if len(password) < 8 {
|
||||
return errors.New("Your password needs to be at-least eight characters long.")
|
||||
}
|
||||
var charMap map[rune]int = make(map[rune]int)
|
||||
var numbers, /*letters, */symbols, upper, lower int
|
||||
for _, char := range password {
|
||||
charItem, ok := charMap[char]
|
||||
if ok {
|
||||
charItem++
|
||||
} else {
|
||||
charItem = 1
|
||||
}
|
||||
charMap[char] = charItem
|
||||
|
||||
if unicode.IsLetter(char) {
|
||||
//letters++
|
||||
if unicode.IsUpper(char) {
|
||||
upper++
|
||||
} else {
|
||||
lower++
|
||||
}
|
||||
} else if unicode.IsNumber(char) {
|
||||
numbers++
|
||||
} else {
|
||||
symbols++
|
||||
}
|
||||
}
|
||||
|
||||
if numbers == 0 {
|
||||
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 {
|
||||
return errors.New("You don't have any uppercase characters in your password.")
|
||||
}
|
||||
if lower == 0 {
|
||||
return errors.New("You don't have any lowercase 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") {
|
||||
return errors.New("You may not have 'test', '123', 'password' or 'qwerty' in your password.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func write_file(name string, content string) (err error) {
|
||||
f, err := os.Create(name)
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/* Copyright Azareal 2017 - 2018 */
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import "bytes"
|
||||
import "sync"
|
||||
import "encoding/json"
|
||||
//import "html/template"
|
||||
|
||||
var docks WidgetDocks
|
||||
var widget_update_mutex sync.RWMutex
|
||||
|
||||
type WidgetDocks struct
|
||||
{
|
||||
LeftSidebar []Widget
|
||||
RightSidebar []Widget
|
||||
//PanelLeft []Menus
|
||||
}
|
||||
|
||||
type Widget struct
|
||||
{
|
||||
Enabled bool
|
||||
Location string // Coming Soon: overview, topics, topic / topic_view, forums, forum, global
|
||||
Position int
|
||||
Body string
|
||||
}
|
||||
|
||||
type NameTextPair struct
|
||||
{
|
||||
Name string
|
||||
Text string
|
||||
}
|
||||
|
||||
func init_widgets() error {
|
||||
rows, err := get_widgets_stmt.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var sbytes []byte
|
||||
var side, wtype, data string
|
||||
|
||||
var leftWidgets []Widget
|
||||
var rightWidgets []Widget
|
||||
|
||||
for rows.Next() {
|
||||
var widget Widget
|
||||
err = rows.Scan(&widget.Position, &side, &wtype, &widget.Enabled, &widget.Location, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sbytes = []byte(data)
|
||||
switch(wtype) {
|
||||
case "simple":
|
||||
var tmp NameTextPair
|
||||
err = json.Unmarshal(sbytes, &tmp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
err = templates.ExecuteTemplate(&b,"widget_simple.html",tmp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
widget.Body = string(b.Bytes())
|
||||
default:
|
||||
widget.Body = data
|
||||
}
|
||||
|
||||
if side == "left" {
|
||||
leftWidgets = append(leftWidgets,widget)
|
||||
} else if side == "right" {
|
||||
rightWidgets = append(rightWidgets,widget)
|
||||
}
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
widget_update_mutex.Lock()
|
||||
docks.LeftSidebar = leftWidgets
|
||||
docks.RightSidebar = rightWidgets
|
||||
widget_update_mutex.Unlock()
|
||||
|
||||
if super_debug {
|
||||
fmt.Println("docks.LeftSidebar",docks.LeftSidebar)
|
||||
fmt.Println("docks.RightSidebar",docks.RightSidebar)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue