// Copyright 2016 Documize Inc. . All rights reserved. // // This software (Documize Community Edition) is licensed under // GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html // // You can operate outside the AGPL restrictions by purchasing // Documize Enterprise Edition and obtaining a commercial license // by contacting . // // https://documize.com // Package boot prepares runtime environment. package boot import ( "crypto/rand" "fmt" "strings" "time" "github.com/documize/community/core/database" "github.com/documize/community/core/env" "github.com/documize/community/core/web" "github.com/jmoiron/sqlx" ) // InitRuntime prepares runtime using command line and environment variables. func InitRuntime(r *env.Runtime) bool { // Prepare DB db, err := sqlx.Open("mysql", stdConn(r.Flags.DBConn)) if err != nil { r.Log.Error("unable to setup database", err) } r.Db = db r.Db.SetMaxIdleConns(30) r.Db.SetMaxOpenConns(100) r.Db.SetConnMaxLifetime(time.Second * 14400) err = r.Db.Ping() if err != nil { r.Log.Error("unable to connect to database, connection string should be of the form: '"+ "username:password@tcp(host:3306)/database'", err) return false } // go into setup mode if required if r.Flags.SiteMode != web.SiteModeOffline { if database.Check(*r) { if err := database.Migrate(true /* the config table exists */); err != nil { r.Log.Error("unable to run database migration", err) return false } } else { r.Log.Info("going into setup mode to prepare new database") } } // Prepare SALT if r.Flags.Salt == "" { b := make([]byte, 17) _, err := rand.Read(b) if err != nil { r.Log.Error("problem using crypto/rand", err) return false } for k, v := range b { if (v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z') || (v >= '0' && v <= '0') { b[k] = v } else { s := fmt.Sprintf("%x", v) b[k] = s[0] } } r.Flags.Salt = string(b) r.Log.Info("please set DOCUMIZESALT or use -salt with this value: " + r.Flags.Salt) } // Prepare HTTP ports if r.Flags.SSLCertFile == "" && r.Flags.SSLKeyFile == "" { if r.Flags.HTTPPort == "" { r.Flags.HTTPPort = "80" } } else { if r.Flags.HTTPPort == "" { r.Flags.HTTPPort = "443" } } return true } var stdParams = map[string]string{ "charset": "utf8", "parseTime": "True", "maxAllowedPacket": "4194304", // 4194304 // 16777216 = 16MB } func stdConn(cs string) string { queryBits := strings.Split(cs, "?") ret := queryBits[0] + "?" retFirst := true if len(queryBits) == 2 { paramBits := strings.Split(queryBits[1], "&") for _, pb := range paramBits { found := false if assignBits := strings.Split(pb, "="); len(assignBits) == 2 { _, found = stdParams[strings.TrimSpace(assignBits[0])] } if !found { // if we can't work out what it is, put it through if retFirst { retFirst = false } else { ret += "&" } ret += pb } } } for k, v := range stdParams { if retFirst { retFirst = false } else { ret += "&" } ret += k + "=" + v } return ret }