2014-04-10 22:20:58 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2014-05-26 04:11:25 +04:00
package setting
2014-04-10 22:20:58 +04:00
import (
2016-12-26 04:16:37 +03:00
"crypto/rand"
"encoding/base64"
2014-04-10 22:20:58 +04:00
"fmt"
2016-12-26 04:16:37 +03:00
"io"
2016-09-07 12:19:44 +03:00
"net/mail"
2014-09-14 21:35:22 +04:00
"net/url"
2014-04-10 22:20:58 +04:00
"os"
"os/exec"
"path"
"path/filepath"
2017-03-17 17:16:08 +03:00
"regexp"
2014-09-16 21:34:09 +04:00
"runtime"
2016-08-12 00:46:33 +03:00
"strconv"
2014-04-10 22:20:58 +04:00
"strings"
2014-07-25 00:31:59 +04:00
"time"
2014-04-10 22:20:58 +04:00
2016-12-26 04:16:37 +03:00
"code.gitea.io/git"
2016-12-22 21:12:23 +03:00
"code.gitea.io/gitea/modules/log"
2017-01-24 01:44:23 +03:00
_ "code.gitea.io/gitea/modules/minwinsvc" // import minwinsvc for windows services
2016-12-22 21:12:23 +03:00
"code.gitea.io/gitea/modules/user"
2017-01-24 01:44:23 +03:00
2014-04-10 22:20:58 +04:00
"github.com/Unknwon/com"
2016-11-27 13:14:25 +03:00
_ "github.com/go-macaron/cache/memcache" // memcache plugin for cache
2015-11-22 01:21:22 +03:00
_ "github.com/go-macaron/cache/redis"
2015-10-16 04:28:12 +03:00
"github.com/go-macaron/session"
2016-11-27 13:14:25 +03:00
_ "github.com/go-macaron/session/redis" // redis plugin for store session
2017-02-20 11:11:13 +03:00
"github.com/go-xorm/core"
2017-02-05 16:06:25 +03:00
ini "gopkg.in/ini.v1"
2016-11-04 14:57:27 +03:00
"strk.kbt.io/projects/go/libravatar"
2014-04-10 22:20:58 +04:00
)
2016-11-27 13:14:25 +03:00
// Scheme describes protocol types
2014-05-26 04:11:25 +04:00
type Scheme string
2014-04-14 02:12:07 +04:00
2016-11-27 13:14:25 +03:00
// enumerates all the scheme types
2014-05-26 04:11:25 +04:00
const (
2016-11-27 13:14:25 +03:00
HTTP Scheme = "http"
HTTPS Scheme = "https"
FCGI Scheme = "fcgi"
UnixSocket Scheme = "unix"
2014-05-26 04:11:25 +04:00
)
2014-04-10 22:20:58 +04:00
2016-11-27 13:14:25 +03:00
// LandingPage describes the default page
2014-11-25 02:47:59 +03:00
type LandingPage string
2016-11-27 13:14:25 +03:00
// enumerates all the landing page types
2014-11-25 02:47:59 +03:00
const (
2016-11-27 13:14:25 +03:00
LandingPageHome LandingPage = "/"
LandingPageExplore LandingPage = "/explore"
2014-11-25 02:47:59 +03:00
)
2016-11-27 13:14:25 +03:00
// settings
2014-04-10 22:20:58 +04:00
var (
2016-11-27 13:14:25 +03:00
// AppVer settings
2016-01-31 23:38:20 +03:00
AppVer string
2017-02-28 03:40:02 +03:00
AppBuiltWith string
2016-01-31 23:38:20 +03:00
AppName string
2016-11-27 13:14:25 +03:00
AppURL string
AppSubURL string
AppSubURLDepth int // Number of slashes
2016-01-31 23:38:20 +03:00
AppPath string
2016-03-10 04:53:42 +03:00
AppDataPath string
2014-05-26 04:11:25 +04:00
2015-12-18 06:31:34 +03:00
// Server settings
2016-08-12 00:46:33 +03:00
Protocol Scheme
Domain string
2016-11-27 13:14:25 +03:00
HTTPAddr string
HTTPPort string
2016-08-12 00:46:33 +03:00
LocalURL string
OfflineMode bool
DisableRouterLog bool
2016-11-27 13:14:25 +03:00
CertFile string
KeyFile string
2016-08-12 00:46:33 +03:00
StaticRootPath string
EnableGzip bool
2016-08-18 02:10:07 +03:00
LandingPageURL LandingPage
2016-08-12 00:46:33 +03:00
UnixSocketPermission uint32
2017-02-05 16:06:25 +03:00
EnablePprof bool
2014-05-26 04:11:25 +04:00
2016-12-29 13:51:15 +03:00
SSH = struct {
2016-02-28 04:48:39 +03:00
Disabled bool ` ini:"DISABLE_SSH" `
StartBuiltinServer bool ` ini:"START_SSH_SERVER" `
Domain string ` ini:"SSH_DOMAIN" `
Port int ` ini:"SSH_PORT" `
2016-12-22 15:26:43 +03:00
ListenHost string ` ini:"SSH_LISTEN_HOST" `
2016-02-28 04:48:39 +03:00
ListenPort int ` ini:"SSH_LISTEN_PORT" `
RootPath string ` ini:"SSH_ROOT_PATH" `
KeyTestPath string ` ini:"SSH_KEY_TEST_PATH" `
KeygenPath string ` ini:"SSH_KEYGEN_PATH" `
MinimumKeySizeCheck bool ` ini:"-" `
MinimumKeySizes map [ string ] int ` ini:"-" `
2016-12-29 13:51:15 +03:00
} {
Disabled : false ,
StartBuiltinServer : false ,
2017-02-14 19:07:37 +03:00
Domain : "" ,
2016-12-29 13:51:15 +03:00
Port : 22 ,
KeygenPath : "ssh-keygen" ,
2016-02-28 04:48:39 +03:00
}
2016-12-26 04:16:37 +03:00
LFS struct {
StartServer bool ` ini:"LFS_START_SERVER" `
ContentPath string ` ini:"LFS_CONTENT_PATH" `
JWTSecretBase64 string ` ini:"LFS_JWT_SECRET" `
JWTSecretBytes [ ] byte ` ini:"-" `
}
2015-12-18 06:31:34 +03:00
// Security settings
2014-06-24 21:55:47 +04:00
InstallLock bool
SecretKey string
LogInRememberDays int
CookieUserName string
CookieRememberName string
ReverseProxyAuthUser string
2016-12-24 16:40:44 +03:00
MinPasswordLength int
2017-01-23 04:19:50 +03:00
ImportLocalPaths bool
2014-04-10 22:20:58 +04:00
2015-12-18 06:31:34 +03:00
// Database settings
2015-02-12 05:58:37 +03:00
UseSQLite3 bool
UseMySQL bool
2016-12-24 04:37:35 +03:00
UseMSSQL bool
2015-02-12 05:58:37 +03:00
UsePostgreSQL bool
2015-09-12 22:31:36 +03:00
UseTiDB bool
2015-02-12 05:58:37 +03:00
2017-01-25 05:43:02 +03:00
// Indexer settings
Indexer struct {
IssuePath string
UpdateQueueLength int
}
2015-12-18 06:31:34 +03:00
// Webhook settings
2016-12-23 10:18:05 +03:00
Webhook = struct {
2015-07-25 16:32:04 +03:00
QueueLength int
2015-02-11 20:04:01 +03:00
DeliverTimeout int
SkipTLSVerify bool
2015-08-26 19:30:06 +03:00
Types [ ] string
2015-08-27 18:06:14 +03:00
PagingNum int
2016-12-23 10:18:05 +03:00
} {
QueueLength : 1000 ,
DeliverTimeout : 5 ,
SkipTLSVerify : false ,
PagingNum : 10 ,
2015-02-11 05:06:59 +03:00
}
2014-06-08 12:45:34 +04:00
2015-12-18 06:31:34 +03:00
// Repository settings
2016-12-23 10:18:05 +03:00
Repository = struct {
2015-10-25 11:26:26 +03:00
AnsiCharset string
ForcePrivate bool
2015-12-10 20:37:53 +03:00
MaxCreationLimit int
2016-08-31 02:18:33 +03:00
MirrorQueueLength int
2015-10-24 10:36:47 +03:00
PullRequestQueueLength int
2016-08-28 10:06:22 +03:00
PreferredLicenses [ ] string
2016-10-04 19:58:14 +03:00
DisableHTTPGit bool
2016-08-12 12:29:29 +03:00
// Repository editor settings
Editor struct {
LineWrapExtensions [ ] string
PreviewableFileModes [ ] string
} ` ini:"-" `
// Repository upload settings
Upload struct {
Enabled bool
TempPath string
AllowedTypes [ ] string ` delim:"|" `
FileMaxSize int64
MaxFiles int
} ` ini:"-" `
2016-12-23 10:18:05 +03:00
} {
AnsiCharset : "" ,
ForcePrivate : false ,
MaxCreationLimit : - 1 ,
MirrorQueueLength : 1000 ,
PullRequestQueueLength : 1000 ,
PreferredLicenses : [ ] string { "Apache License 2.0,MIT License" } ,
DisableHTTPGit : false ,
// Repository editor settings
Editor : struct {
LineWrapExtensions [ ] string
PreviewableFileModes [ ] string
} {
LineWrapExtensions : strings . Split ( ".txt,.md,.markdown,.mdown,.mkd," , "," ) ,
PreviewableFileModes : [ ] string { "markdown" } ,
} ,
// Repository upload settings
Upload : struct {
Enabled bool
TempPath string
AllowedTypes [ ] string ` delim:"|" `
FileMaxSize int64
MaxFiles int
} {
Enabled : true ,
TempPath : "data/tmp/uploads" ,
AllowedTypes : [ ] string { } ,
FileMaxSize : 3 ,
MaxFiles : 5 ,
} ,
2015-10-24 10:36:47 +03:00
}
2015-07-24 21:52:25 +03:00
RepoRootPath string
2016-12-23 10:18:05 +03:00
ScriptType = "bash"
2015-07-24 21:52:25 +03:00
2015-12-18 06:31:34 +03:00
// UI settings
2016-12-23 10:18:05 +03:00
UI = struct {
2016-07-23 19:23:54 +03:00
ExplorePagingNum int
IssuePagingNum int
FeedMaxCommitNum int
ThemeColorMetaTag string
MaxDisplayFileSize int64
2017-01-01 05:51:10 +03:00
ShowUserEmail bool
2016-07-23 19:23:54 +03:00
Admin struct {
UserPagingNum int
RepoPagingNum int
NoticePagingNum int
OrgPagingNum int
} ` ini:"ui.admin" `
User struct {
RepoPagingNum int
} ` ini:"ui.user" `
2017-04-01 04:03:01 +03:00
Meta struct {
Author string
Description string
Keywords string
} ` ini:"ui.meta" `
2016-12-23 10:18:05 +03:00
} {
ExplorePagingNum : 20 ,
IssuePagingNum : 10 ,
FeedMaxCommitNum : 5 ,
ThemeColorMetaTag : ` #6cc644 ` ,
MaxDisplayFileSize : 8388608 ,
Admin : struct {
UserPagingNum int
RepoPagingNum int
NoticePagingNum int
OrgPagingNum int
} {
UserPagingNum : 50 ,
RepoPagingNum : 50 ,
NoticePagingNum : 25 ,
OrgPagingNum : 50 ,
} ,
User : struct {
RepoPagingNum int
} {
RepoPagingNum : 15 ,
} ,
2017-04-01 04:03:01 +03:00
Meta : struct {
Author string
Description string
Keywords string
} {
Author : "Gitea - Git with a cup of tea" ,
Description : "Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go" ,
Keywords : "go,git,self-hosted,gitea" ,
} ,
2016-07-23 19:23:54 +03:00
}
2014-04-10 22:20:58 +04:00
2017-03-15 03:52:01 +03:00
// Markdown settings
2016-12-23 10:18:05 +03:00
Markdown = struct {
2015-09-01 15:32:02 +03:00
EnableHardLineBreak bool
2016-01-14 09:20:03 +03:00
CustomURLSchemes [ ] string ` ini:"CUSTOM_URL_SCHEMES" `
2016-08-12 12:29:29 +03:00
FileExtensions [ ] string
2016-12-23 10:18:05 +03:00
} {
EnableHardLineBreak : false ,
FileExtensions : strings . Split ( ".md,.markdown,.mdown,.mkd" , "," ) ,
2015-09-01 15:32:02 +03:00
}
2017-02-14 15:16:00 +03:00
// Admin settings
Admin struct {
DisableRegularOrgCreation bool
}
2015-12-18 06:31:34 +03:00
// Picture settings
2016-08-07 21:01:47 +03:00
AvatarUploadPath string
GravatarSource string
DisableGravatar bool
EnableFederatedAvatar bool
LibravatarService * libravatar . Libravatar
2014-05-26 04:11:25 +04:00
2015-12-18 06:31:34 +03:00
// Log settings
2014-05-28 09:53:06 +04:00
LogRootPath string
LogModes [ ] string
LogConfigs [ ] string
2014-04-10 22:20:58 +04:00
2015-12-18 06:31:34 +03:00
// Attachment settings
2014-07-23 23:15:47 +04:00
AttachmentPath string
AttachmentAllowedTypes string
2014-07-24 17:19:59 +04:00
AttachmentMaxSize int64
AttachmentMaxFiles int
2014-07-24 17:51:40 +04:00
AttachmentEnabled bool
2014-07-23 23:15:47 +04:00
2015-12-18 06:31:34 +03:00
// Time settings
2014-07-25 00:31:59 +04:00
TimeFormat string
2015-12-18 06:31:34 +03:00
// Cache settings
2014-08-01 01:25:34 +04:00
CacheAdapter string
2016-08-11 15:59:11 +03:00
CacheInterval int
2014-08-01 01:25:34 +04:00
CacheConn string
2014-04-10 22:20:58 +04:00
2015-12-18 06:31:34 +03:00
// Session settings
2016-03-13 04:56:03 +03:00
SessionConfig session . Options
CSRFCookieName = "_csrf"
2014-04-10 22:20:58 +04:00
2015-12-18 06:31:34 +03:00
// Cron tasks
2016-12-23 10:18:05 +03:00
Cron = struct {
2015-08-17 21:19:29 +03:00
UpdateMirror struct {
Enabled bool
RunAtStart bool
Schedule string
} ` ini:"cron.update_mirrors" `
RepoHealthCheck struct {
Enabled bool
RunAtStart bool
Schedule string
2015-12-09 19:38:12 +03:00
Timeout time . Duration
2015-08-17 21:19:29 +03:00
Args [ ] string ` delim:" " `
} ` ini:"cron.repo_health_check" `
CheckRepoStats struct {
Enabled bool
RunAtStart bool
Schedule string
} ` ini:"cron.check_repo_stats" `
2017-02-11 07:00:46 +03:00
ArchiveCleanup struct {
Enabled bool
RunAtStart bool
Schedule string
OlderThan time . Duration
} ` ini:"cron.archive_cleanup" `
2016-12-23 10:18:05 +03:00
} {
UpdateMirror : struct {
Enabled bool
RunAtStart bool
Schedule string
} {
2017-03-01 18:10:12 +03:00
Enabled : true ,
RunAtStart : false ,
Schedule : "@every 10m" ,
2016-12-23 10:18:05 +03:00
} ,
RepoHealthCheck : struct {
Enabled bool
RunAtStart bool
Schedule string
Timeout time . Duration
Args [ ] string ` delim:" " `
} {
2017-03-01 18:10:12 +03:00
Enabled : true ,
RunAtStart : false ,
Schedule : "@every 24h" ,
Timeout : 60 * time . Second ,
Args : [ ] string { } ,
2016-12-23 10:18:05 +03:00
} ,
CheckRepoStats : struct {
Enabled bool
RunAtStart bool
Schedule string
} {
2017-03-01 18:10:12 +03:00
Enabled : true ,
2016-12-23 10:18:05 +03:00
RunAtStart : true ,
Schedule : "@every 24h" ,
} ,
2017-02-11 07:00:46 +03:00
ArchiveCleanup : struct {
Enabled bool
RunAtStart bool
Schedule string
OlderThan time . Duration
} {
2017-03-01 18:10:12 +03:00
Enabled : true ,
2017-02-11 07:00:46 +03:00
RunAtStart : true ,
Schedule : "@every 24h" ,
OlderThan : 24 * time . Hour ,
} ,
2015-01-02 15:14:43 +03:00
}
2014-09-17 22:22:51 +04:00
2016-07-04 12:27:06 +03:00
// Git settings
2016-12-23 10:18:05 +03:00
Git = struct {
2017-02-13 14:49:42 +03:00
Version string ` ini:"-" `
2016-08-07 19:49:47 +03:00
DisableDiffHighlight bool
2016-07-04 12:27:06 +03:00
MaxGitDiffLines int
MaxGitDiffLineCharacters int
MaxGitDiffFiles int
2016-08-10 03:24:32 +03:00
GCArgs [ ] string ` delim:" " `
2016-07-04 12:27:06 +03:00
Timeout struct {
Migrate int
Mirror int
Clone int
Pull int
2016-08-10 03:24:32 +03:00
GC int ` ini:"GC" `
2016-07-04 12:27:06 +03:00
} ` ini:"git.timeout" `
2016-12-23 10:18:05 +03:00
} {
DisableDiffHighlight : false ,
MaxGitDiffLines : 1000 ,
MaxGitDiffLineCharacters : 500 ,
MaxGitDiffFiles : 100 ,
GCArgs : [ ] string { } ,
Timeout : struct {
Migrate int
Mirror int
Clone int
Pull int
GC int ` ini:"GC" `
} {
Migrate : 600 ,
Mirror : 300 ,
Clone : 300 ,
Pull : 300 ,
GC : 60 ,
} ,
2016-07-04 12:27:06 +03:00
}
2016-08-10 09:58:15 +03:00
// Mirror settings
2016-12-23 10:18:05 +03:00
Mirror = struct {
2016-08-10 09:47:16 +03:00
DefaultInterval int
2016-12-23 10:18:05 +03:00
} {
DefaultInterval : 8 ,
2016-08-10 09:47:16 +03:00
}
2016-07-04 12:27:06 +03:00
// API settings
2016-12-23 10:18:05 +03:00
API = struct {
2016-07-04 12:27:06 +03:00
MaxResponseItems int
2016-12-23 10:18:05 +03:00
} {
MaxResponseItems : 50 ,
2016-07-04 12:27:06 +03:00
}
2015-12-18 06:31:34 +03:00
// I18n settings
2016-11-27 13:14:25 +03:00
Langs [ ] string
Names [ ] string
dateLangs map [ string ] string
2014-09-17 22:22:51 +04:00
2017-03-15 03:52:01 +03:00
// Highlight settings are loaded in modules/template/highlight.go
2015-12-18 06:31:34 +03:00
// Other settings
2016-09-01 08:01:32 +03:00
ShowFooterBranding bool
ShowFooterVersion bool
ShowFooterTemplateLoadTime bool
2015-03-23 17:19:19 +03:00
2015-12-18 06:31:34 +03:00
// Global setting objects
2014-12-31 13:37:29 +03:00
Cfg * ini . File
2015-12-18 06:31:34 +03:00
CustomPath string // Custom directory path
2015-02-05 13:12:37 +03:00
CustomConf string
2017-01-09 14:54:57 +03:00
CustomPID string
2014-07-26 08:24:27 +04:00
ProdMode bool
RunUser string
2014-09-16 21:34:09 +04:00
IsWindows bool
2014-09-22 03:39:10 +04:00
HasRobotsTxt bool
2014-04-10 22:20:58 +04:00
)
2016-08-18 02:10:07 +03:00
// DateLang transforms standard language locale name to corresponding value in datetime plugin.
2015-08-05 10:24:26 +03:00
func DateLang ( lang string ) string {
name , ok := dateLangs [ lang ]
if ok {
return name
}
return "en"
}
2015-11-09 00:59:56 +03:00
// execPath returns the executable path.
func execPath ( ) ( string , error ) {
2014-05-26 04:11:25 +04:00
file , err := exec . LookPath ( os . Args [ 0 ] )
if err != nil {
return "" , err
}
2015-11-09 00:59:56 +03:00
return filepath . Abs ( file )
}
func init ( ) {
IsWindows = runtime . GOOS == "windows"
log . NewLogger ( 0 , "console" , ` { "level": 0} ` )
var err error
if AppPath , err = execPath ( ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to get app path: %v" , err )
2014-05-26 04:11:25 +04:00
}
2015-11-09 00:59:56 +03:00
// Note: we don't use path.Dir here because it does not handle case
// which path starts with two "/" in Windows: "//psf/Home/..."
AppPath = strings . Replace ( AppPath , "\\" , "/" , - 1 )
2014-06-11 03:11:53 +04:00
}
// WorkDir returns absolute path of work directory.
func WorkDir ( ) ( string , error ) {
2016-11-07 13:41:50 +03:00
wd := os . Getenv ( "GITEA_WORK_DIR" )
2015-09-07 21:06:05 +03:00
if len ( wd ) > 0 {
return wd , nil
}
2016-11-07 13:41:50 +03:00
// Use GOGS_WORK_DIR if available, for backward compatibility
// TODO: drop in 1.1.0 ?
wd = os . Getenv ( "GOGS_WORK_DIR" )
if len ( wd ) > 0 {
log . Warn ( ` Usage of GOGS_WORK_DIR is deprecated and will be * removed * in a future release ,
please consider changing to GITEA_WORK_DIR ` )
return wd , nil
}
2015-09-07 21:06:05 +03:00
2015-11-09 00:59:56 +03:00
i := strings . LastIndex ( AppPath , "/" )
2015-08-02 06:41:28 +03:00
if i == - 1 {
2015-11-09 00:59:56 +03:00
return AppPath , nil
2015-08-02 06:41:28 +03:00
}
2015-11-09 00:59:56 +03:00
return AppPath [ : i ] , nil
2014-05-26 04:11:25 +04:00
}
2015-03-18 11:25:55 +03:00
func forcePathSeparator ( path string ) {
if strings . Contains ( path , "\\" ) {
2015-03-18 13:37:44 +03:00
log . Fatal ( 4 , "Do not use '\\' or '\\\\' in paths, instead, please use '/' in all places" )
2015-03-18 11:25:55 +03:00
}
}
2016-08-10 03:41:18 +03:00
// IsRunUserMatchCurrentUser returns false if configured run user does not match
// actual user that runs the app. The first return value is the actual user name.
// This check is ignored under Windows since SSH remote login is not the main
// method to login on Windows.
func IsRunUserMatchCurrentUser ( runUser string ) ( string , bool ) {
if IsWindows {
return "" , true
}
currentUser := user . CurrentUsername ( )
return currentUser , runUser == currentUser
}
2017-01-09 14:54:57 +03:00
func createPIDFile ( pidPath string ) {
currentPid := os . Getpid ( )
if err := os . MkdirAll ( filepath . Dir ( pidPath ) , os . ModePerm ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to create PID folder: %v" , err )
2017-01-09 14:54:57 +03:00
}
file , err := os . Create ( pidPath )
if err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to create PID file: %v" , err )
2017-01-09 14:54:57 +03:00
}
defer file . Close ( )
if _ , err := file . WriteString ( strconv . FormatInt ( int64 ( currentPid ) , 10 ) ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to write PID information: %v" , err )
2017-01-09 14:54:57 +03:00
}
}
2015-09-17 06:08:46 +03:00
// NewContext initializes configuration context.
2014-05-26 04:57:01 +04:00
// NOTE: do not print any log except error.
2015-09-17 06:08:46 +03:00
func NewContext ( ) {
2014-05-26 04:11:25 +04:00
workDir , err := WorkDir ( )
if err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to get work directory: %v" , err )
2014-05-26 04:11:25 +04:00
}
2016-12-22 21:12:23 +03:00
Cfg = ini . Empty ( )
2016-11-07 13:41:50 +03:00
CustomPath = os . Getenv ( "GITEA_CUSTOM" )
2014-05-26 04:11:25 +04:00
if len ( CustomPath ) == 0 {
2016-11-07 13:41:50 +03:00
// For backward compatibility
// TODO: drop in 1.1.0 ?
CustomPath = os . Getenv ( "GOGS_CUSTOM" )
if len ( CustomPath ) == 0 {
CustomPath = workDir + "/custom"
} else {
log . Warn ( ` Usage of GOGS_CUSTOM is deprecated and will be * removed * in a future release ,
please consider changing to GITEA_CUSTOM ` )
}
2014-05-26 04:11:25 +04:00
}
2017-01-14 05:15:43 +03:00
if len ( CustomPID ) > 0 {
createPIDFile ( CustomPID )
2017-01-09 14:54:57 +03:00
}
2015-02-05 13:12:37 +03:00
if len ( CustomConf ) == 0 {
2015-08-02 06:52:48 +03:00
CustomConf = CustomPath + "/conf/app.ini"
2015-02-05 13:12:37 +03:00
}
if com . IsFile ( CustomConf ) {
if err = Cfg . Append ( CustomConf ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to load custom conf '%s': %v" , CustomConf , err )
2014-05-26 04:11:25 +04:00
}
} else {
2015-12-20 05:43:32 +03:00
log . Warn ( "Custom config '%s' not found, ignore this if you're running first time" , CustomConf )
2014-05-26 04:11:25 +04:00
}
2015-01-02 15:14:43 +03:00
Cfg . NameMapper = ini . AllCapsUnderscore
2014-05-26 04:11:25 +04:00
2015-12-20 05:43:32 +03:00
homeDir , err := com . HomeDir ( )
if err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to get home directory: %v" , err )
2015-12-20 05:43:32 +03:00
}
homeDir = strings . Replace ( homeDir , "\\" , "/" , - 1 )
2014-12-31 13:37:29 +03:00
LogRootPath = Cfg . Section ( "log" ) . Key ( "ROOT_PATH" ) . MustString ( path . Join ( workDir , "log" ) )
2015-03-18 11:25:55 +03:00
forcePathSeparator ( LogRootPath )
2014-12-31 13:37:29 +03:00
sec := Cfg . Section ( "server" )
2016-12-02 08:23:37 +03:00
AppName = Cfg . Section ( "" ) . Key ( "APP_NAME" ) . MustString ( "Gitea: Git with a cup of tea" )
2016-11-27 13:14:25 +03:00
AppURL = sec . Key ( "ROOT_URL" ) . MustString ( "http://localhost:3000/" )
2017-03-03 15:47:24 +03:00
AppURL = strings . TrimRight ( AppURL , "/" ) + "/"
2014-05-26 04:11:25 +04:00
2014-09-20 04:11:34 +04:00
// Check if has app suburl.
2016-11-27 13:14:25 +03:00
url , err := url . Parse ( AppURL )
2014-09-14 21:35:22 +04:00
if err != nil {
2016-11-27 13:14:25 +03:00
log . Fatal ( 4 , "Invalid ROOT_URL '%s': %s" , AppURL , err )
2014-09-14 21:35:22 +04:00
}
2016-01-31 23:38:20 +03:00
// Suburl should start with '/' and end without '/', such as '/{subpath}'.
2016-08-07 20:13:05 +03:00
// This value is empty if site does not have sub-url.
2016-11-27 13:14:25 +03:00
AppSubURL = strings . TrimSuffix ( url . Path , "/" )
AppSubURLDepth = strings . Count ( AppSubURL , "/" )
2014-09-14 21:35:22 +04:00
2014-05-26 04:11:25 +04:00
Protocol = HTTP
2014-12-31 13:37:29 +03:00
if sec . Key ( "PROTOCOL" ) . String ( ) == "https" {
2014-05-26 04:11:25 +04:00
Protocol = HTTPS
2014-12-31 13:37:29 +03:00
CertFile = sec . Key ( "CERT_FILE" ) . String ( )
KeyFile = sec . Key ( "KEY_FILE" ) . String ( )
} else if sec . Key ( "PROTOCOL" ) . String ( ) == "fcgi" {
2014-11-04 04:46:53 +03:00
Protocol = FCGI
2016-08-12 00:46:33 +03:00
} else if sec . Key ( "PROTOCOL" ) . String ( ) == "unix" {
2016-11-27 13:14:25 +03:00
Protocol = UnixSocket
2016-08-12 00:55:10 +03:00
UnixSocketPermissionRaw := sec . Key ( "UNIX_SOCKET_PERMISSION" ) . MustString ( "666" )
UnixSocketPermissionParsed , err := strconv . ParseUint ( UnixSocketPermissionRaw , 8 , 32 )
if err != nil || UnixSocketPermissionParsed > 0777 {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to parse unixSocketPermission: %s" , UnixSocketPermissionRaw )
2016-08-12 00:55:10 +03:00
}
UnixSocketPermission = uint32 ( UnixSocketPermissionParsed )
2014-11-04 04:46:53 +03:00
}
2014-12-31 13:37:29 +03:00
Domain = sec . Key ( "DOMAIN" ) . MustString ( "localhost" )
2016-08-12 00:55:10 +03:00
HTTPAddr = sec . Key ( "HTTP_ADDR" ) . MustString ( "0.0.0.0" )
HTTPPort = sec . Key ( "HTTP_PORT" ) . MustString ( "3000" )
LocalURL = sec . Key ( "LOCAL_ROOT_URL" ) . MustString ( string ( Protocol ) + "://localhost:" + HTTPPort + "/" )
2014-12-31 13:37:29 +03:00
OfflineMode = sec . Key ( "OFFLINE_MODE" ) . MustBool ( )
DisableRouterLog = sec . Key ( "DISABLE_ROUTER_LOG" ) . MustBool ( )
StaticRootPath = sec . Key ( "STATIC_ROOT_PATH" ) . MustString ( workDir )
2016-03-10 04:53:42 +03:00
AppDataPath = sec . Key ( "APP_DATA_PATH" ) . MustString ( "data" )
2014-12-31 13:37:29 +03:00
EnableGzip = sec . Key ( "ENABLE_GZIP" ) . MustBool ( )
2017-02-05 16:06:25 +03:00
EnablePprof = sec . Key ( "ENABLE_PPROF" ) . MustBool ( false )
2014-12-31 13:37:29 +03:00
switch sec . Key ( "LANDING_PAGE" ) . MustString ( "home" ) {
2014-11-25 02:47:59 +03:00
case "explore" :
2016-11-27 13:14:25 +03:00
LandingPageURL = LandingPageExplore
2014-11-25 02:47:59 +03:00
default :
2016-11-27 13:14:25 +03:00
LandingPageURL = LandingPageHome
2014-11-25 02:47:59 +03:00
}
2017-02-14 19:07:37 +03:00
if len ( SSH . Domain ) == 0 {
SSH . Domain = Domain
}
2016-02-28 04:48:39 +03:00
SSH . RootPath = path . Join ( homeDir , ".ssh" )
SSH . KeyTestPath = os . TempDir ( )
if err = Cfg . Section ( "server" ) . MapTo ( & SSH ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map SSH settings: %v" , err )
2016-02-28 04:48:39 +03:00
}
2016-12-22 21:12:23 +03:00
SSH . KeygenPath = sec . Key ( "SSH_KEYGEN_PATH" ) . MustString ( "ssh-keygen" )
SSH . Port = sec . Key ( "SSH_PORT" ) . MustInt ( 22 )
2017-01-08 06:14:45 +03:00
SSH . ListenPort = sec . Key ( "SSH_LISTEN_PORT" ) . MustInt ( SSH . Port )
2016-12-22 21:12:23 +03:00
2016-02-28 04:48:39 +03:00
// When disable SSH, start builtin server value is ignored.
if SSH . Disabled {
SSH . StartBuiltinServer = false
}
if ! SSH . Disabled && ! SSH . StartBuiltinServer {
if err := os . MkdirAll ( SSH . RootPath , 0700 ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to create '%s': %v" , SSH . RootPath , err )
2016-02-28 04:48:39 +03:00
} else if err = os . MkdirAll ( SSH . KeyTestPath , 0644 ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to create '%s': %v" , SSH . KeyTestPath , err )
2016-02-28 04:48:39 +03:00
}
}
SSH . MinimumKeySizeCheck = sec . Key ( "MINIMUM_KEY_SIZE_CHECK" ) . MustBool ( )
SSH . MinimumKeySizes = map [ string ] int { }
minimumKeySizes := Cfg . Section ( "ssh.minimum_key_sizes" ) . Keys ( )
for _ , key := range minimumKeySizes {
if key . MustInt ( ) != - 1 {
SSH . MinimumKeySizes [ strings . ToLower ( key . Name ( ) ) ] = key . MustInt ( )
}
}
2016-12-26 04:16:37 +03:00
if err = Cfg . Section ( "server" ) . MapTo ( & LFS ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map LFS settings: %v" , err )
2016-12-26 04:16:37 +03:00
}
if LFS . StartServer {
if err := os . MkdirAll ( LFS . ContentPath , 0700 ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to create '%s': %v" , LFS . ContentPath , err )
2016-12-26 04:16:37 +03:00
}
LFS . JWTSecretBytes = make ( [ ] byte , 32 )
n , err := base64 . RawURLEncoding . Decode ( LFS . JWTSecretBytes , [ ] byte ( LFS . JWTSecretBase64 ) )
if err != nil || n != 32 {
//Generate new secret and save to config
_ , err := io . ReadFull ( rand . Reader , LFS . JWTSecretBytes )
if err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Error reading random bytes: %v" , err )
2016-12-26 04:16:37 +03:00
}
LFS . JWTSecretBase64 = base64 . RawURLEncoding . EncodeToString ( LFS . JWTSecretBytes )
// Save secret
cfg := ini . Empty ( )
if com . IsFile ( CustomConf ) {
// Keeps custom settings if there is already something.
if err := cfg . Append ( CustomConf ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Error ( 4 , "Failed to load custom conf '%s': %v" , CustomConf , err )
2016-12-26 04:16:37 +03:00
}
}
cfg . Section ( "server" ) . Key ( "LFS_JWT_SECRET" ) . SetValue ( LFS . JWTSecretBase64 )
2017-01-09 17:36:23 +03:00
if err := os . MkdirAll ( filepath . Dir ( CustomConf ) , os . ModePerm ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to create '%s': %v" , CustomConf , err )
2017-01-09 17:36:23 +03:00
}
2016-12-26 04:16:37 +03:00
if err := cfg . SaveTo ( CustomConf ) ; err != nil {
log . Fatal ( 4 , "Error saving generated JWT Secret to custom config: %v" , err )
return
}
}
//Disable LFS client hooks if installed for the current OS user
//Needs at least git v2.1.2
binVersion , err := git . BinVersion ( )
if err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Error retrieving git version: %v" , err )
2016-12-26 04:16:37 +03:00
}
splitVersion := strings . SplitN ( binVersion , "." , 3 )
majorVersion , err := strconv . ParseUint ( splitVersion [ 0 ] , 10 , 64 )
if err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Error parsing git major version: %v" , err )
2016-12-26 04:16:37 +03:00
}
minorVersion , err := strconv . ParseUint ( splitVersion [ 1 ] , 10 , 64 )
if err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Error parsing git minor version: %v" , err )
2016-12-26 04:16:37 +03:00
}
revisionVersion , err := strconv . ParseUint ( splitVersion [ 2 ] , 10 , 64 )
if err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Error parsing git revision version: %v" , err )
2016-12-26 04:16:37 +03:00
}
if ! ( ( majorVersion > 2 ) || ( majorVersion == 2 && minorVersion > 1 ) ||
( majorVersion == 2 && minorVersion == 1 && revisionVersion >= 2 ) ) {
LFS . StartServer = false
log . Error ( 4 , "LFS server support needs at least Git v2.1.2" )
} else {
git . GlobalCommandArgs = append ( git . GlobalCommandArgs , "-c" , "filter.lfs.required=" ,
"-c" , "filter.lfs.smudge=" , "-c" , "filter.lfs.clean=" )
}
}
2014-12-31 13:37:29 +03:00
sec = Cfg . Section ( "security" )
2016-12-23 10:18:05 +03:00
InstallLock = sec . Key ( "INSTALL_LOCK" ) . MustBool ( false )
SecretKey = sec . Key ( "SECRET_KEY" ) . MustString ( "!#@FDEWREWR&*(" )
LogInRememberDays = sec . Key ( "LOGIN_REMEMBER_DAYS" ) . MustInt ( 7 )
CookieUserName = sec . Key ( "COOKIE_USERNAME" ) . MustString ( "gitea_awesome" )
CookieRememberName = sec . Key ( "COOKIE_REMEMBER_NAME" ) . MustString ( "gitea_incredible" )
2014-12-31 13:37:29 +03:00
ReverseProxyAuthUser = sec . Key ( "REVERSE_PROXY_AUTHENTICATION_USER" ) . MustString ( "X-WEBAUTH-USER" )
2016-12-24 17:42:11 +03:00
MinPasswordLength = sec . Key ( "MIN_PASSWORD_LENGTH" ) . MustInt ( 6 )
2017-01-23 04:19:50 +03:00
ImportLocalPaths = sec . Key ( "IMPORT_LOCAL_PATHS" ) . MustBool ( false )
2014-12-31 13:37:29 +03:00
sec = Cfg . Section ( "attachment" )
2015-10-30 03:40:57 +03:00
AttachmentPath = sec . Key ( "PATH" ) . MustString ( path . Join ( AppDataPath , "attachments" ) )
2015-02-15 01:49:33 +03:00
if ! filepath . IsAbs ( AttachmentPath ) {
AttachmentPath = path . Join ( workDir , AttachmentPath )
}
2017-01-15 17:57:00 +03:00
AttachmentAllowedTypes = strings . Replace ( sec . Key ( "ALLOWED_TYPES" ) . MustString ( "image/jpeg,image/png,application/zip,application/gzip" ) , "|" , "," , - 1 )
2015-09-02 23:18:09 +03:00
AttachmentMaxSize = sec . Key ( "MAX_SIZE" ) . MustInt64 ( 4 )
2015-08-11 18:24:40 +03:00
AttachmentMaxFiles = sec . Key ( "MAX_FILES" ) . MustInt ( 5 )
2014-12-31 13:37:29 +03:00
AttachmentEnabled = sec . Key ( "ENABLE" ) . MustBool ( true )
2014-07-23 23:15:47 +04:00
2017-02-04 15:37:50 +03:00
TimeFormatKey := Cfg . Section ( "time" ) . Key ( "FORMAT" ) . MustString ( "RFC1123" )
2014-08-01 08:24:29 +04:00
TimeFormat = map [ string ] string {
"ANSIC" : time . ANSIC ,
"UnixDate" : time . UnixDate ,
"RubyDate" : time . RubyDate ,
"RFC822" : time . RFC822 ,
"RFC822Z" : time . RFC822Z ,
"RFC850" : time . RFC850 ,
"RFC1123" : time . RFC1123 ,
"RFC1123Z" : time . RFC1123Z ,
"RFC3339" : time . RFC3339 ,
"RFC3339Nano" : time . RFC3339Nano ,
"Kitchen" : time . Kitchen ,
"Stamp" : time . Stamp ,
"StampMilli" : time . StampMilli ,
"StampMicro" : time . StampMicro ,
"StampNano" : time . StampNano ,
2017-02-04 15:37:50 +03:00
} [ TimeFormatKey ]
// When the TimeFormatKey does not exist in the previous map e.g.'2006-01-02 15:04:05'
if len ( TimeFormat ) == 0 {
TimeFormat = TimeFormatKey
TestTimeFormat , _ := time . Parse ( TimeFormat , TimeFormat )
if TestTimeFormat . Format ( time . RFC3339 ) != "2006-01-02T15:04:05Z" {
log . Fatal ( 4 , "Can't create time properly, please check your time format has 2006, 01, 02, 15, 04 and 05" )
}
log . Trace ( "Custom TimeFormat: %s" , TimeFormat )
}
2014-07-25 00:31:59 +04:00
2016-12-22 21:12:23 +03:00
RunUser = Cfg . Section ( "" ) . Key ( "RUN_USER" ) . MustString ( user . CurrentUsername ( ) )
2014-05-26 04:11:25 +04:00
// Does not check run user when the install lock is off.
2016-08-10 03:41:18 +03:00
if InstallLock {
currentUser , match := IsRunUserMatchCurrentUser ( RunUser )
if ! match {
log . Fatal ( 4 , "Expect user '%s' but current user is: %s" , RunUser , currentUser )
}
2014-05-26 04:11:25 +04:00
}
2014-12-07 04:22:48 +03:00
// Determine and create root git repository path.
2014-12-31 13:37:29 +03:00
sec = Cfg . Section ( "repository" )
2016-10-04 19:58:14 +03:00
Repository . DisableHTTPGit = sec . Key ( "DISABLE_HTTP_GIT" ) . MustBool ( )
2016-11-07 16:26:13 +03:00
RepoRootPath = sec . Key ( "ROOT" ) . MustString ( path . Join ( homeDir , "gitea-repositories" ) )
2015-03-18 11:25:55 +03:00
forcePathSeparator ( RepoRootPath )
2014-06-24 10:28:47 +04:00
if ! filepath . IsAbs ( RepoRootPath ) {
2015-03-18 11:25:55 +03:00
RepoRootPath = path . Join ( workDir , RepoRootPath )
2014-06-24 10:28:47 +04:00
} else {
2015-03-18 11:25:55 +03:00
RepoRootPath = path . Clean ( RepoRootPath )
2014-06-24 10:28:47 +04:00
}
2014-12-31 13:37:29 +03:00
ScriptType = sec . Key ( "SCRIPT_TYPE" ) . MustString ( "bash" )
2015-12-10 20:37:53 +03:00
if err = Cfg . Section ( "repository" ) . MapTo ( & Repository ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map Repository settings: %v" , err )
2016-08-12 12:29:29 +03:00
} else if err = Cfg . Section ( "repository.editor" ) . MapTo ( & Repository . Editor ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map Repository.Editor settings: %v" , err )
2016-08-12 12:29:29 +03:00
} else if err = Cfg . Section ( "repository.upload" ) . MapTo ( & Repository . Upload ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map Repository.Upload settings: %v" , err )
2015-12-10 20:37:53 +03:00
}
2014-05-26 04:11:25 +04:00
2016-08-12 12:29:29 +03:00
if ! filepath . IsAbs ( Repository . Upload . TempPath ) {
Repository . Upload . TempPath = path . Join ( workDir , Repository . Upload . TempPath )
2016-08-11 15:48:08 +03:00
}
2014-12-31 13:37:29 +03:00
sec = Cfg . Section ( "picture" )
2015-10-30 03:40:57 +03:00
AvatarUploadPath = sec . Key ( "AVATAR_UPLOAD_PATH" ) . MustString ( path . Join ( AppDataPath , "avatars" ) )
2015-03-18 11:25:55 +03:00
forcePathSeparator ( AvatarUploadPath )
2015-02-15 01:49:33 +03:00
if ! filepath . IsAbs ( AvatarUploadPath ) {
AvatarUploadPath = path . Join ( workDir , AvatarUploadPath )
}
2015-08-10 03:44:43 +03:00
switch source := sec . Key ( "GRAVATAR_SOURCE" ) . MustString ( "gravatar" ) ; source {
2014-11-17 04:27:04 +03:00
case "duoshuo" :
GravatarSource = "http://gravatar.duoshuo.com/avatar/"
2015-08-10 03:44:43 +03:00
case "gravatar" :
2016-01-29 08:06:17 +03:00
GravatarSource = "https://secure.gravatar.com/avatar/"
2016-12-19 19:04:39 +03:00
case "libravatar" :
GravatarSource = "https://seccdn.libravatar.org/avatar/"
2015-08-10 03:44:43 +03:00
default :
GravatarSource = source
2014-11-17 04:27:04 +03:00
}
2014-12-31 13:37:29 +03:00
DisableGravatar = sec . Key ( "DISABLE_GRAVATAR" ) . MustBool ( )
2016-08-07 20:27:38 +03:00
EnableFederatedAvatar = sec . Key ( "ENABLE_FEDERATED_AVATAR" ) . MustBool ( )
2015-03-25 01:38:12 +03:00
if OfflineMode {
DisableGravatar = true
2016-08-07 20:27:38 +03:00
EnableFederatedAvatar = false
}
2016-08-07 21:01:47 +03:00
if DisableGravatar {
EnableFederatedAvatar = false
}
2016-08-07 20:27:38 +03:00
2016-08-07 21:01:47 +03:00
if EnableFederatedAvatar {
2016-08-07 20:27:38 +03:00
LibravatarService = libravatar . New ( )
parts := strings . Split ( GravatarSource , "/" )
if len ( parts ) >= 3 {
if parts [ 0 ] == "https:" {
LibravatarService . SetUseHTTPS ( true )
LibravatarService . SetSecureFallbackHost ( parts [ 2 ] )
} else {
LibravatarService . SetUseHTTPS ( false )
LibravatarService . SetFallbackHost ( parts [ 2 ] )
}
}
2015-03-25 01:38:12 +03:00
}
2014-07-26 08:24:27 +04:00
2016-07-23 19:23:54 +03:00
if err = Cfg . Section ( "ui" ) . MapTo ( & UI ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map UI settings: %v" , err )
2016-07-23 19:23:54 +03:00
} else if err = Cfg . Section ( "markdown" ) . MapTo ( & Markdown ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map Markdown settings: %v" , err )
2017-02-14 15:16:00 +03:00
} else if err = Cfg . Section ( "admin" ) . MapTo ( & Admin ) ; err != nil {
log . Fatal ( 4 , "Fail to map Admin settings: %v" , err )
2016-01-24 09:54:21 +03:00
} else if err = Cfg . Section ( "cron" ) . MapTo ( & Cron ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map Cron settings: %v" , err )
2016-07-04 12:27:06 +03:00
} else if err = Cfg . Section ( "git" ) . MapTo ( & Git ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map Git settings: %v" , err )
2016-08-10 09:47:16 +03:00
} else if err = Cfg . Section ( "mirror" ) . MapTo ( & Mirror ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map Mirror settings: %v" , err )
2016-08-10 09:58:15 +03:00
} else if err = Cfg . Section ( "api" ) . MapTo ( & API ) ; err != nil {
2017-01-29 23:13:57 +03:00
log . Fatal ( 4 , "Failed to map API settings: %v" , err )
2016-08-10 09:47:16 +03:00
}
if Mirror . DefaultInterval <= 0 {
Mirror . DefaultInterval = 24
2015-01-02 15:14:43 +03:00
}
2014-09-17 08:03:03 +04:00
2014-12-31 13:37:29 +03:00
Langs = Cfg . Section ( "i18n" ) . Key ( "LANGS" ) . Strings ( "," )
2016-12-22 21:12:23 +03:00
if len ( Langs ) == 0 {
2016-12-23 10:18:05 +03:00
Langs = defaultLangs
2016-12-22 21:12:23 +03:00
}
2014-12-31 13:37:29 +03:00
Names = Cfg . Section ( "i18n" ) . Key ( "NAMES" ) . Strings ( "," )
2016-12-22 21:12:23 +03:00
if len ( Names ) == 0 {
2016-12-23 10:18:05 +03:00
Names = defaultLangNames
2016-12-22 21:12:23 +03:00
}
2015-08-05 10:24:26 +03:00
dateLangs = Cfg . Section ( "i18n.datelang" ) . KeysHash ( )
2014-09-22 03:39:10 +04:00
2016-12-23 10:18:05 +03:00
ShowFooterBranding = Cfg . Section ( "other" ) . Key ( "SHOW_FOOTER_BRANDING" ) . MustBool ( false )
ShowFooterVersion = Cfg . Section ( "other" ) . Key ( "SHOW_FOOTER_VERSION" ) . MustBool ( true )
ShowFooterTemplateLoadTime = Cfg . Section ( "other" ) . Key ( "SHOW_FOOTER_TEMPLATE_LOAD_TIME" ) . MustBool ( true )
2015-03-23 17:19:19 +03:00
2017-01-01 05:51:10 +03:00
UI . ShowUserEmail = Cfg . Section ( "ui" ) . Key ( "SHOW_USER_EMAIL" ) . MustBool ( true )
2014-09-22 03:39:10 +04:00
HasRobotsTxt = com . IsFile ( path . Join ( CustomPath , "robots.txt" ) )
2014-05-26 04:11:25 +04:00
}
2016-11-27 13:14:25 +03:00
// Service settings
2014-04-10 22:20:58 +04:00
var Service struct {
2015-03-25 15:59:48 +03:00
ActiveCodeLives int
ResetPwdCodeLives int
2014-12-06 01:54:57 +03:00
RegisterEmailConfirm bool
DisableRegistration bool
2015-02-05 19:09:26 +03:00
ShowRegistrationButton bool
2014-12-06 01:54:57 +03:00
RequireSignInView bool
EnableNotifyMail bool
EnableReverseProxyAuth bool
EnableReverseProxyAutoRegister bool
2015-09-13 18:07:21 +03:00
EnableCaptcha bool
2017-01-08 06:12:03 +03:00
DefaultKeepEmailPrivate bool
NoReplyAddress string
2017-03-29 13:57:43 +03:00
// OpenID settings
EnableOpenIDSignIn bool
EnableOpenIDSignUp bool
OpenIDWhitelist [ ] * regexp . Regexp
OpenIDBlacklist [ ] * regexp . Regexp
2014-04-10 22:20:58 +04:00
}
2014-05-26 04:11:25 +04:00
func newService ( ) {
2015-03-25 15:59:48 +03:00
sec := Cfg . Section ( "service" )
Service . ActiveCodeLives = sec . Key ( "ACTIVE_CODE_LIVE_MINUTES" ) . MustInt ( 180 )
Service . ResetPwdCodeLives = sec . Key ( "RESET_PASSWD_CODE_LIVE_MINUTES" ) . MustInt ( 180 )
Service . DisableRegistration = sec . Key ( "DISABLE_REGISTRATION" ) . MustBool ( )
Service . ShowRegistrationButton = sec . Key ( "SHOW_REGISTRATION_BUTTON" ) . MustBool ( ! Service . DisableRegistration )
Service . RequireSignInView = sec . Key ( "REQUIRE_SIGNIN_VIEW" ) . MustBool ( )
Service . EnableReverseProxyAuth = sec . Key ( "ENABLE_REVERSE_PROXY_AUTHENTICATION" ) . MustBool ( )
Service . EnableReverseProxyAutoRegister = sec . Key ( "ENABLE_REVERSE_PROXY_AUTO_REGISTRATION" ) . MustBool ( )
2015-09-13 18:07:21 +03:00
Service . EnableCaptcha = sec . Key ( "ENABLE_CAPTCHA" ) . MustBool ( )
2017-01-08 06:12:03 +03:00
Service . DefaultKeepEmailPrivate = sec . Key ( "DEFAULT_KEEP_EMAIL_PRIVATE" ) . MustBool ( )
Service . NoReplyAddress = sec . Key ( "NO_REPLY_ADDRESS" ) . MustString ( "noreply.example.org" )
2017-03-29 13:57:43 +03:00
sec = Cfg . Section ( "openid" )
Service . EnableOpenIDSignIn = sec . Key ( "ENABLE_OPENID_SIGNIN" ) . MustBool ( true )
Service . EnableOpenIDSignUp = sec . Key ( "ENABLE_OPENID_SIGNUP" ) . MustBool ( ! Service . DisableRegistration )
pats := sec . Key ( "WHITELISTED_URIS" ) . Strings ( " " )
if len ( pats ) != 0 {
Service . OpenIDWhitelist = make ( [ ] * regexp . Regexp , len ( pats ) )
for i , p := range pats {
Service . OpenIDWhitelist [ i ] = regexp . MustCompilePOSIX ( p )
}
}
pats = sec . Key ( "BLACKLISTED_URIS" ) . Strings ( " " )
if len ( pats ) != 0 {
Service . OpenIDBlacklist = make ( [ ] * regexp . Regexp , len ( pats ) )
for i , p := range pats {
Service . OpenIDBlacklist [ i ] = regexp . MustCompilePOSIX ( p )
}
}
2014-04-10 22:20:58 +04:00
}
var logLevels = map [ string ] string {
"Trace" : "0" ,
"Debug" : "1" ,
"Info" : "2" ,
"Warn" : "3" ,
"Error" : "4" ,
"Critical" : "5" ,
}
func newLogService ( ) {
2017-02-28 03:40:02 +03:00
log . Info ( "Gitea v%s%s" , AppVer , AppBuiltWith )
2014-04-10 22:20:58 +04:00
2014-12-31 13:37:29 +03:00
LogModes = strings . Split ( Cfg . Section ( "log" ) . Key ( "MODE" ) . MustString ( "console" ) , "," )
2014-05-11 22:37:12 +04:00
LogConfigs = make ( [ ] string , len ( LogModes ) )
2016-12-22 21:12:23 +03:00
2017-01-17 09:02:35 +03:00
useConsole := false
2017-02-20 11:11:13 +03:00
for i := 0 ; i < len ( LogModes ) ; i ++ {
LogModes [ i ] = strings . TrimSpace ( LogModes [ i ] )
if LogModes [ i ] == "console" {
2017-01-17 09:02:35 +03:00
useConsole = true
}
}
2017-02-20 11:11:13 +03:00
2017-01-23 04:19:50 +03:00
if ! useConsole {
2017-01-17 09:02:35 +03:00
log . DelLogger ( "console" )
}
2014-05-11 22:37:12 +04:00
for i , mode := range LogModes {
2014-12-31 13:37:29 +03:00
sec , err := Cfg . GetSection ( "log." + mode )
if err != nil {
2016-12-22 21:12:23 +03:00
sec , _ = Cfg . NewSection ( "log." + mode )
2014-05-11 22:37:12 +04:00
}
2015-02-27 03:45:38 +03:00
validLevels := [ ] string { "Trace" , "Debug" , "Info" , "Warn" , "Error" , "Critical" }
2014-05-11 22:37:12 +04:00
// Log level.
2015-02-27 03:45:38 +03:00
levelName := Cfg . Section ( "log." + mode ) . Key ( "LEVEL" ) . In (
Cfg . Section ( "log" ) . Key ( "LEVEL" ) . In ( "Trace" , validLevels ) ,
validLevels )
2014-05-11 22:37:12 +04:00
level , ok := logLevels [ levelName ]
if ! ok {
2014-07-26 08:24:27 +04:00
log . Fatal ( 4 , "Unknown log level: %s" , levelName )
2014-05-11 22:37:12 +04:00
}
// Generate log configuration.
switch mode {
case "console" :
LogConfigs [ i ] = fmt . Sprintf ( ` { "level":%s} ` , level )
case "file" :
2017-01-23 14:19:12 +03:00
logPath := sec . Key ( "FILE_NAME" ) . MustString ( path . Join ( LogRootPath , "gitea.log" ) )
2015-12-08 09:11:40 +03:00
if err = os . MkdirAll ( path . Dir ( logPath ) , os . ModePerm ) ; err != nil {
panic ( err . Error ( ) )
}
2014-05-11 22:37:12 +04:00
LogConfigs [ i ] = fmt . Sprintf (
` { "level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d} ` , level ,
logPath ,
2014-12-31 13:37:29 +03:00
sec . Key ( "LOG_ROTATE" ) . MustBool ( true ) ,
sec . Key ( "MAX_LINES" ) . MustInt ( 1000000 ) ,
1 << uint ( sec . Key ( "MAX_SIZE_SHIFT" ) . MustInt ( 28 ) ) ,
sec . Key ( "DAILY_ROTATE" ) . MustBool ( true ) ,
sec . Key ( "MAX_DAYS" ) . MustInt ( 7 ) )
2014-05-11 22:37:12 +04:00
case "conn" :
2014-06-20 08:25:23 +04:00
LogConfigs [ i ] = fmt . Sprintf ( ` { "level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"} ` , level ,
2014-12-31 13:37:29 +03:00
sec . Key ( "RECONNECT_ON_MSG" ) . MustBool ( ) ,
sec . Key ( "RECONNECT" ) . MustBool ( ) ,
sec . Key ( "PROTOCOL" ) . In ( "tcp" , [ ] string { "tcp" , "unix" , "udp" } ) ,
sec . Key ( "ADDR" ) . MustString ( ":7020" ) )
2014-05-11 22:37:12 +04:00
case "smtp" :
2016-12-22 15:27:13 +03:00
LogConfigs [ i ] = fmt . Sprintf ( ` { "level":%s,"username":"%s","password":"%s","host":"%s","sendTos":["%s"],"subject":"%s"} ` , level ,
2014-12-31 13:37:29 +03:00
sec . Key ( "USER" ) . MustString ( "example@example.com" ) ,
sec . Key ( "PASSWD" ) . MustString ( "******" ) ,
sec . Key ( "HOST" ) . MustString ( "127.0.0.1:25" ) ,
2016-12-22 15:27:13 +03:00
strings . Replace ( sec . Key ( "RECEIVERS" ) . MustString ( "example@example.com" ) , "," , "\",\"" , - 1 ) ,
2014-12-31 13:37:29 +03:00
sec . Key ( "SUBJECT" ) . MustString ( "Diagnostic message from serve" ) )
2014-05-11 22:37:12 +04:00
case "database" :
2014-06-20 08:25:23 +04:00
LogConfigs [ i ] = fmt . Sprintf ( ` { "level":%s,"driver":"%s","conn":"%s"} ` , level ,
2014-12-31 13:37:29 +03:00
sec . Key ( "DRIVER" ) . String ( ) ,
sec . Key ( "CONN" ) . String ( ) )
2014-05-11 22:37:12 +04:00
}
2014-12-31 13:37:29 +03:00
log . NewLogger ( Cfg . Section ( "log" ) . Key ( "BUFFER_LEN" ) . MustInt64 ( 10000 ) , mode , LogConfigs [ i ] )
2014-05-11 22:37:12 +04:00
log . Info ( "Log Mode: %s(%s)" , strings . Title ( mode ) , levelName )
2014-04-10 22:20:58 +04:00
}
}
2017-02-20 11:11:13 +03:00
// NewXORMLogService initializes xorm logger service
func NewXORMLogService ( disableConsole bool ) {
logModes := strings . Split ( Cfg . Section ( "log" ) . Key ( "MODE" ) . MustString ( "console" ) , "," )
var logConfigs string
for _ , mode := range logModes {
mode = strings . TrimSpace ( mode )
if disableConsole && mode == "console" {
continue
}
2017-02-21 16:34:05 +03:00
2017-02-20 11:11:13 +03:00
sec , err := Cfg . GetSection ( "log." + mode )
if err != nil {
2017-02-21 16:34:05 +03:00
sec , _ = Cfg . NewSection ( "log." + mode )
2017-02-20 11:11:13 +03:00
}
validLevels := [ ] string { "Trace" , "Debug" , "Info" , "Warn" , "Error" , "Critical" }
// Log level.
levelName := Cfg . Section ( "log." + mode ) . Key ( "LEVEL" ) . In (
Cfg . Section ( "log" ) . Key ( "LEVEL" ) . In ( "Trace" , validLevels ) ,
validLevels )
level , ok := logLevels [ levelName ]
if ! ok {
log . Fatal ( 4 , "Unknown log level: %s" , levelName )
}
// Generate log configuration.
switch mode {
case "console" :
logConfigs = fmt . Sprintf ( ` { "level":%s} ` , level )
case "file" :
logPath := sec . Key ( "FILE_NAME" ) . MustString ( path . Join ( LogRootPath , "xorm.log" ) )
if err = os . MkdirAll ( path . Dir ( logPath ) , os . ModePerm ) ; err != nil {
panic ( err . Error ( ) )
}
logPath = filepath . Join ( filepath . Dir ( logPath ) , "xorm.log" )
logConfigs = fmt . Sprintf (
` { "level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d} ` , level ,
logPath ,
sec . Key ( "LOG_ROTATE" ) . MustBool ( true ) ,
sec . Key ( "MAX_LINES" ) . MustInt ( 1000000 ) ,
1 << uint ( sec . Key ( "MAX_SIZE_SHIFT" ) . MustInt ( 28 ) ) ,
sec . Key ( "DAILY_ROTATE" ) . MustBool ( true ) ,
sec . Key ( "MAX_DAYS" ) . MustInt ( 7 ) )
case "conn" :
logConfigs = fmt . Sprintf ( ` { "level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"} ` , level ,
sec . Key ( "RECONNECT_ON_MSG" ) . MustBool ( ) ,
sec . Key ( "RECONNECT" ) . MustBool ( ) ,
sec . Key ( "PROTOCOL" ) . In ( "tcp" , [ ] string { "tcp" , "unix" , "udp" } ) ,
sec . Key ( "ADDR" ) . MustString ( ":7020" ) )
case "smtp" :
logConfigs = fmt . Sprintf ( ` { "level":%s,"username":"%s","password":"%s","host":"%s","sendTos":"%s","subject":"%s"} ` , level ,
sec . Key ( "USER" ) . MustString ( "example@example.com" ) ,
sec . Key ( "PASSWD" ) . MustString ( "******" ) ,
sec . Key ( "HOST" ) . MustString ( "127.0.0.1:25" ) ,
sec . Key ( "RECEIVERS" ) . MustString ( "[]" ) ,
sec . Key ( "SUBJECT" ) . MustString ( "Diagnostic message from serve" ) )
case "database" :
logConfigs = fmt . Sprintf ( ` { "level":%s,"driver":"%s","conn":"%s"} ` , level ,
sec . Key ( "DRIVER" ) . String ( ) ,
sec . Key ( "CONN" ) . String ( ) )
}
log . NewXORMLogger ( Cfg . Section ( "log" ) . Key ( "BUFFER_LEN" ) . MustInt64 ( 10000 ) , mode , logConfigs )
2017-02-21 16:34:05 +03:00
if ! disableConsole {
log . Info ( "XORM Log Mode: %s(%s)" , strings . Title ( mode ) , levelName )
}
2017-02-20 11:11:13 +03:00
var lvl core . LogLevel
switch levelName {
case "Trace" , "Debug" :
lvl = core . LOG_DEBUG
case "Info" :
lvl = core . LOG_INFO
case "Warn" :
lvl = core . LOG_WARNING
case "Error" , "Critical" :
lvl = core . LOG_ERR
}
log . XORMLogger . SetLevel ( lvl )
}
2017-02-22 14:44:51 +03:00
if len ( logConfigs ) == 0 {
log . DiscardXORMLogger ( )
}
2017-02-20 11:11:13 +03:00
}
2014-04-10 22:20:58 +04:00
func newCacheService ( ) {
2014-12-31 13:37:29 +03:00
CacheAdapter = Cfg . Section ( "cache" ) . Key ( "ADAPTER" ) . In ( "memory" , [ ] string { "memory" , "redis" , "memcache" } )
2014-04-10 22:20:58 +04:00
switch CacheAdapter {
case "memory" :
2016-08-11 15:59:11 +03:00
CacheInterval = Cfg . Section ( "cache" ) . Key ( "INTERVAL" ) . MustInt ( 60 )
2014-04-10 22:20:58 +04:00
case "redis" , "memcache" :
2014-12-31 13:37:29 +03:00
CacheConn = strings . Trim ( Cfg . Section ( "cache" ) . Key ( "HOST" ) . String ( ) , "\" " )
2014-04-10 22:20:58 +04:00
default :
2014-07-26 08:24:27 +04:00
log . Fatal ( 4 , "Unknown cache adapter: %s" , CacheAdapter )
2014-04-10 22:20:58 +04:00
}
log . Info ( "Cache Service Enabled" )
}
func newSessionService ( ) {
2014-12-31 13:37:29 +03:00
SessionConfig . Provider = Cfg . Section ( "session" ) . Key ( "PROVIDER" ) . In ( "memory" ,
2014-05-19 06:05:35 +04:00
[ ] string { "memory" , "file" , "redis" , "mysql" } )
2014-12-31 13:37:29 +03:00
SessionConfig . ProviderConfig = strings . Trim ( Cfg . Section ( "session" ) . Key ( "PROVIDER_CONFIG" ) . String ( ) , "\" " )
2016-12-27 18:02:24 +03:00
SessionConfig . CookieName = Cfg . Section ( "session" ) . Key ( "COOKIE_NAME" ) . MustString ( "i_like_gitea" )
2016-11-27 13:14:25 +03:00
SessionConfig . CookiePath = AppSubURL
2016-12-23 10:18:05 +03:00
SessionConfig . Secure = Cfg . Section ( "session" ) . Key ( "COOKIE_SECURE" ) . MustBool ( false )
2014-12-31 13:37:29 +03:00
SessionConfig . Gclifetime = Cfg . Section ( "session" ) . Key ( "GC_INTERVAL_TIME" ) . MustInt64 ( 86400 )
SessionConfig . Maxlifetime = Cfg . Section ( "session" ) . Key ( "SESSION_LIFE_TIME" ) . MustInt64 ( 86400 )
2014-04-10 22:20:58 +04:00
log . Info ( "Session Service Enabled" )
}
2014-05-26 04:11:25 +04:00
// Mailer represents mail service.
type Mailer struct {
2016-12-29 13:51:15 +03:00
// Mailer
2016-05-30 11:32:01 +03:00
QueueLength int
Name string
From string
2016-09-07 12:19:44 +03:00
FromEmail string
2016-12-25 16:55:22 +03:00
EnableHTMLAlternative bool
// SMTP sender
2016-12-29 13:51:15 +03:00
Host string
User , Passwd string
DisableHelo bool
HeloHostname string
SkipVerify bool
UseCertificate bool
CertFile , KeyFile string
2016-12-25 16:55:22 +03:00
// Sendmail sender
2016-12-29 13:51:15 +03:00
UseSendmail bool
SendmailPath string
2014-05-26 04:11:25 +04:00
}
var (
2016-11-27 13:14:25 +03:00
// MailService the global mailer
2015-09-17 23:11:44 +03:00
MailService * Mailer
2014-05-26 04:11:25 +04:00
)
2014-04-10 22:20:58 +04:00
func newMailService ( ) {
2014-12-31 13:37:29 +03:00
sec := Cfg . Section ( "mailer" )
2014-04-10 22:20:58 +04:00
// Check mailer setting.
2014-12-31 13:37:29 +03:00
if ! sec . Key ( "ENABLED" ) . MustBool ( ) {
2014-04-10 22:20:58 +04:00
return
}
MailService = & Mailer {
2016-12-29 13:51:15 +03:00
QueueLength : sec . Key ( "SEND_BUFFER_LEN" ) . MustInt ( 100 ) ,
Name : sec . Key ( "NAME" ) . MustString ( AppName ) ,
2016-12-25 16:55:22 +03:00
EnableHTMLAlternative : sec . Key ( "ENABLE_HTML_ALTERNATIVE" ) . MustBool ( ) ,
2016-12-29 13:51:15 +03:00
Host : sec . Key ( "HOST" ) . String ( ) ,
User : sec . Key ( "USER" ) . String ( ) ,
Passwd : sec . Key ( "PASSWD" ) . String ( ) ,
DisableHelo : sec . Key ( "DISABLE_HELO" ) . MustBool ( ) ,
HeloHostname : sec . Key ( "HELO_HOSTNAME" ) . String ( ) ,
SkipVerify : sec . Key ( "SKIP_VERIFY" ) . MustBool ( ) ,
UseCertificate : sec . Key ( "USE_CERTIFICATE" ) . MustBool ( ) ,
CertFile : sec . Key ( "CERT_FILE" ) . String ( ) ,
KeyFile : sec . Key ( "KEY_FILE" ) . String ( ) ,
UseSendmail : sec . Key ( "USE_SENDMAIL" ) . MustBool ( ) ,
SendmailPath : sec . Key ( "SENDMAIL_PATH" ) . MustString ( "sendmail" ) ,
2014-04-10 22:20:58 +04:00
}
2014-12-31 13:37:29 +03:00
MailService . From = sec . Key ( "FROM" ) . MustString ( MailService . User )
2016-09-07 12:19:44 +03:00
parsed , err := mail . ParseAddress ( MailService . From )
if err != nil {
log . Fatal ( 4 , "Invalid mailer.FROM (%s): %v" , MailService . From , err )
}
MailService . FromEmail = parsed . Address
2014-04-10 22:20:58 +04:00
log . Info ( "Mail Service Enabled" )
}
func newRegisterMailService ( ) {
2014-12-31 13:37:29 +03:00
if ! Cfg . Section ( "service" ) . Key ( "REGISTER_EMAIL_CONFIRM" ) . MustBool ( ) {
2014-04-10 22:20:58 +04:00
return
} else if MailService == nil {
log . Warn ( "Register Mail Service: Mail Service is not enabled" )
return
}
Service . RegisterEmailConfirm = true
log . Info ( "Register Mail Service Enabled" )
}
func newNotifyMailService ( ) {
2014-12-31 13:37:29 +03:00
if ! Cfg . Section ( "service" ) . Key ( "ENABLE_NOTIFY_MAIL" ) . MustBool ( ) {
2014-04-10 22:20:58 +04:00
return
} else if MailService == nil {
log . Warn ( "Notify Mail Service: Mail Service is not enabled" )
return
}
2014-06-21 08:51:41 +04:00
Service . EnableNotifyMail = true
2014-04-10 22:20:58 +04:00
log . Info ( "Notify Mail Service Enabled" )
}
2014-06-08 12:45:34 +04:00
func newWebhookService ( ) {
2015-02-11 05:06:59 +03:00
sec := Cfg . Section ( "webhook" )
2015-07-25 16:32:04 +03:00
Webhook . QueueLength = sec . Key ( "QUEUE_LENGTH" ) . MustInt ( 1000 )
2015-02-11 05:06:59 +03:00
Webhook . DeliverTimeout = sec . Key ( "DELIVER_TIMEOUT" ) . MustInt ( 5 )
2015-02-11 20:04:01 +03:00
Webhook . SkipTLSVerify = sec . Key ( "SKIP_TLS_VERIFY" ) . MustBool ( )
2015-08-26 19:30:06 +03:00
Webhook . Types = [ ] string { "gogs" , "slack" }
2015-08-27 18:06:14 +03:00
Webhook . PagingNum = sec . Key ( "PAGING_NUM" ) . MustInt ( 10 )
2014-06-08 12:45:34 +04:00
}
2016-11-27 13:14:25 +03:00
// NewServices initializes the services
2014-05-26 04:11:25 +04:00
func NewServices ( ) {
2014-04-10 22:20:58 +04:00
newService ( )
newLogService ( )
2017-02-20 11:11:13 +03:00
NewXORMLogService ( false )
2014-04-10 22:20:58 +04:00
newCacheService ( )
newSessionService ( )
newMailService ( )
newRegisterMailService ( )
newNotifyMailService ( )
2014-06-08 12:45:34 +04:00
newWebhookService ( )
2014-04-10 22:20:58 +04:00
}