aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/auth/repo_form.go2
-rw-r--r--modules/base/markdown.go48
-rw-r--r--modules/base/template.go66
-rw-r--r--modules/base/tool.go27
-rw-r--r--modules/git/hooks.go111
-rw-r--r--modules/git/repo_tag.go12
-rw-r--r--modules/git/utils.go21
-rw-r--r--modules/git/version.go4
-rw-r--r--modules/mailer/mailer.go55
-rw-r--r--modules/middleware/context.go8
-rw-r--r--modules/middleware/repo.go10
-rw-r--r--modules/setting/setting.go2
12 files changed, 268 insertions, 98 deletions
diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go
index 233f7b10..df5b8b69 100644
--- a/modules/auth/repo_form.go
+++ b/modules/auth/repo_form.go
@@ -102,7 +102,7 @@ func (f *NewSlackHookForm) Validate(ctx *macaron.Context, errs *binding.Errors,
// \/ \/ \/
type CreateIssueForm struct {
- IssueName string `form:"title" binding:"Required;MaxSize(50)"`
+ IssueName string `form:"title" binding:"Required;MaxSize(255)"`
MilestoneId int64 `form:"milestoneid"`
AssigneeId int64 `form:"assigneeid"`
Labels string `form:"labels"`
diff --git a/modules/base/markdown.go b/modules/base/markdown.go
index a3db15df..cb083200 100644
--- a/modules/base/markdown.go
+++ b/modules/base/markdown.go
@@ -13,7 +13,8 @@ import (
"regexp"
"strings"
- "github.com/gogits/gfm"
+ "github.com/russross/blackfriday"
+
"github.com/gogits/gogs/modules/setting"
)
@@ -74,7 +75,7 @@ func IsReadmeFile(name string) bool {
}
type CustomRender struct {
- gfm.Renderer
+ blackfriday.Renderer
urlPrefix string
}
@@ -154,39 +155,40 @@ func RenderSpecialLink(rawBytes []byte, urlPrefix string) []byte {
func RenderRawMarkdown(body []byte, urlPrefix string) []byte {
htmlFlags := 0
- // htmlFlags |= gfm.HTML_USE_XHTML
- // htmlFlags |= gfm.HTML_USE_SMARTYPANTS
- // htmlFlags |= gfm.HTML_SMARTYPANTS_FRACTIONS
- // htmlFlags |= gfm.HTML_SMARTYPANTS_LATEX_DASHES
- // htmlFlags |= gfm.HTML_SKIP_HTML
- htmlFlags |= gfm.HTML_SKIP_STYLE
- htmlFlags |= gfm.HTML_SKIP_SCRIPT
- htmlFlags |= gfm.HTML_GITHUB_BLOCKCODE
- htmlFlags |= gfm.HTML_OMIT_CONTENTS
- // htmlFlags |= gfm.HTML_COMPLETE_PAGE
+ // htmlFlags |= blackfriday.HTML_USE_XHTML
+ // htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
+ // htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
+ // htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
+ // htmlFlags |= blackfriday.HTML_SKIP_HTML
+ htmlFlags |= blackfriday.HTML_SKIP_STYLE
+ // htmlFlags |= blackfriday.HTML_SKIP_SCRIPT
+ // htmlFlags |= blackfriday.HTML_GITHUB_BLOCKCODE
+ htmlFlags |= blackfriday.HTML_OMIT_CONTENTS
+ // htmlFlags |= blackfriday.HTML_COMPLETE_PAGE
renderer := &CustomRender{
- Renderer: gfm.HtmlRenderer(htmlFlags, "", ""),
+ Renderer: blackfriday.HtmlRenderer(htmlFlags, "", ""),
urlPrefix: urlPrefix,
}
// set up the parser
extensions := 0
- extensions |= gfm.EXTENSION_NO_INTRA_EMPHASIS
- extensions |= gfm.EXTENSION_TABLES
- extensions |= gfm.EXTENSION_FENCED_CODE
- extensions |= gfm.EXTENSION_AUTOLINK
- extensions |= gfm.EXTENSION_STRIKETHROUGH
- extensions |= gfm.EXTENSION_HARD_LINE_BREAK
- extensions |= gfm.EXTENSION_SPACE_HEADERS
- extensions |= gfm.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK
-
- body = gfm.Markdown(body, renderer, extensions)
+ extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
+ extensions |= blackfriday.EXTENSION_TABLES
+ extensions |= blackfriday.EXTENSION_FENCED_CODE
+ extensions |= blackfriday.EXTENSION_AUTOLINK
+ extensions |= blackfriday.EXTENSION_STRIKETHROUGH
+ extensions |= blackfriday.EXTENSION_HARD_LINE_BREAK
+ extensions |= blackfriday.EXTENSION_SPACE_HEADERS
+ extensions |= blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK
+
+ body = blackfriday.Markdown(body, renderer, extensions)
return body
}
func RenderMarkdown(rawBytes []byte, urlPrefix string) []byte {
body := RenderSpecialLink(rawBytes, urlPrefix)
body = RenderRawMarkdown(body, urlPrefix)
+ body = XSS(body)
return body
}
diff --git a/modules/base/template.go b/modules/base/template.go
index b1c8c161..6d25cd45 100644
--- a/modules/base/template.go
+++ b/modules/base/template.go
@@ -5,7 +5,6 @@
package base
import (
- "bytes"
"container/list"
"encoding/json"
"errors"
@@ -107,7 +106,6 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
return a + b
},
"ActionIcon": ActionIcon,
- "ActionDesc": ActionDesc,
"DateFormat": DateFormat,
"List": List,
"Mail2Domain": func(mail string) string {
@@ -162,19 +160,6 @@ func ActionIcon(opType int) string {
}
}
-// FIXME: Legacy
-const (
- TPL_CREATE_REPO = `<a href="%s/user/%s">%s</a> created repository <a href="%s">%s</a>`
- TPL_COMMIT_REPO = `<a href="%s/user/%s">%s</a> pushed to <a href="%s/src/%s">%s</a> at <a href="%s">%s</a>%s`
- TPL_COMMIT_REPO_LI = `<div><img src="%s?s=16" alt="user-avatar"/> <a href="%s/commit/%s" rel="nofollow">%s</a> %s</div>`
- TPL_CREATE_ISSUE = `<a href="%s/user/%s">%s</a> opened issue <a href="%s/issues/%s">%s#%s</a>
-<div><img src="%s?s=16" alt="user-avatar"/> %s</div>`
- TPL_TRANSFER_REPO = `<a href="%s/user/%s">%s</a> transfered repository <code>%s</code> to <a href="%s">%s</a>`
- TPL_PUSH_TAG = `<a href="%s/user/%s">%s</a> pushed tag <a href="%s/src/%s" rel="nofollow">%s</a> at <a href="%s">%s</a>`
- TPL_COMMENT_ISSUE = `<a href="%s/user/%s">%s</a> commented on issue <a href="%s/issues/%s">%s#%s</a>
-<div><img src="%s?s=16" alt="user-avatar"/> %s</div>`
-)
-
type PushCommit struct {
Sha1 string
Message string
@@ -183,8 +168,9 @@ type PushCommit struct {
}
type PushCommits struct {
- Len int
- Commits []*PushCommit
+ Len int
+ Commits []*PushCommit
+ CompareUrl string
}
func ActionContent2Commits(act Actioner) *PushCommits {
@@ -195,52 +181,6 @@ func ActionContent2Commits(act Actioner) *PushCommits {
return push
}
-// FIXME: Legacy
-// ActionDesc accepts int that represents action operation type
-// and returns the description.
-func ActionDesc(act Actioner) string {
- actUserName := act.GetActUserName()
- email := act.GetActEmail()
- repoUserName := act.GetRepoUserName()
- repoName := act.GetRepoName()
- repoLink := repoUserName + "/" + repoName
- branch := act.GetBranch()
- content := act.GetContent()
- switch act.GetOpType() {
- case 1: // Create repository.
- return fmt.Sprintf(TPL_CREATE_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, repoName)
- case 5: // Commit repository.
- var push *PushCommits
- if err := json.Unmarshal([]byte(content), &push); err != nil {
- return err.Error()
- }
- buf := bytes.NewBuffer([]byte("\n"))
- for _, commit := range push.Commits {
- buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, AvatarLink(commit.AuthorEmail), repoLink, commit.Sha1, commit.Sha1[:7], commit.Message) + "\n")
- }
- if push.Len > 3 {
- buf.WriteString(fmt.Sprintf(`<div><a href="{{AppRootSubUrl}}/%s/%s/commits/%s" rel="nofollow">%d other commits >></a></div>`, actUserName, repoName, branch, push.Len))
- }
- return fmt.Sprintf(TPL_COMMIT_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, branch, branch, repoLink, repoLink,
- buf.String())
- case 6: // Create issue.
- infos := strings.SplitN(content, "|", 2)
- return fmt.Sprintf(TPL_CREATE_ISSUE, setting.AppSubUrl, actUserName, actUserName, repoLink, infos[0], repoLink, infos[0],
- AvatarLink(email), infos[1])
- case 8: // Transfer repository.
- newRepoLink := content + "/" + repoName
- return fmt.Sprintf(TPL_TRANSFER_REPO, setting.AppSubUrl, actUserName, actUserName, repoLink, newRepoLink, newRepoLink)
- case 9: // Push tag.
- return fmt.Sprintf(TPL_PUSH_TAG, setting.AppSubUrl, actUserName, actUserName, repoLink, branch, branch, repoLink, repoLink)
- case 10: // Comment issue.
- infos := strings.SplitN(content, "|", 2)
- return fmt.Sprintf(TPL_COMMENT_ISSUE, setting.AppSubUrl, actUserName, actUserName, repoLink, infos[0], repoLink, infos[0],
- AvatarLink(email), infos[1])
- default:
- return "invalid type"
- }
-}
-
func DiffTypeToStr(diffType int) string {
diffTypes := map[int]string{
1: "add", 2: "modify", 3: "del",
diff --git a/modules/base/tool.go b/modules/base/tool.go
index b4083d09..38fd1e21 100644
--- a/modules/base/tool.go
+++ b/modules/base/tool.go
@@ -14,6 +14,7 @@ import (
"hash"
"html/template"
"math"
+ "regexp"
"strings"
"time"
@@ -446,3 +447,29 @@ func DateFormat(t time.Time, format string) string {
format = replacer.Replace(format)
return t.Format(format)
}
+
+type xssFilter struct {
+ reg *regexp.Regexp
+ repl []byte
+}
+
+var (
+ whiteSpace = []byte(" ")
+ xssFilters = []xssFilter{
+ {regexp.MustCompile(`\ [ONon]\w*=["]*`), whiteSpace},
+ {regexp.MustCompile(`<[SCRIPTscript]{6}`), whiteSpace},
+ {regexp.MustCompile(`=[` + "`" + `'"]*[JAVASCRIPTjavascript \t\0&#x0D;]*:`), whiteSpace},
+ }
+)
+
+// XSS goes through all the XSS filters to make user input content as safe as possible.
+func XSS(in []byte) []byte {
+ for _, filter := range xssFilters {
+ in = filter.reg.ReplaceAll(in, filter.repl)
+ }
+ return in
+}
+
+func XSSString(in string) string {
+ return string(XSS([]byte(in)))
+}
diff --git a/modules/git/hooks.go b/modules/git/hooks.go
new file mode 100644
index 00000000..5b3c88a9
--- /dev/null
+++ b/modules/git/hooks.go
@@ -0,0 +1,111 @@
+// 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.
+
+package git
+
+import (
+ "errors"
+ "io/ioutil"
+ "os"
+ "path"
+ "strings"
+)
+
+// hookNames is a list of Git hooks' name that are supported.
+var hookNames = []string{
+ "pre-applypatch",
+ "applypatch-msg",
+ "prepare-commit-msg",
+ "commit-msg",
+ "pre-commit",
+ "pre-rebase",
+ "post-commit",
+ "post-receive",
+ "post-update",
+}
+
+var (
+ ErrNotValidHook = errors.New("not a valid Git hook")
+)
+
+// IsValidHookName returns true if given name is a valid Git hook.
+func IsValidHookName(name string) bool {
+ for _, hn := range hookNames {
+ if hn == name {
+ return true
+ }
+ }
+ return false
+}
+
+// Hook represents a Git hook.
+type Hook struct {
+ name string
+ IsActive bool // Indicates whether repository has this hook.
+ Content string // Content of hook if it's active.
+ Sample string // Sample content from Git.
+ path string // Hook file path.
+}
+
+// GetHook returns a Git hook by given name and repository.
+func GetHook(repoPath, name string) (*Hook, error) {
+ if !IsValidHookName(name) {
+ return nil, ErrNotValidHook
+ }
+ h := &Hook{
+ name: name,
+ path: path.Join(repoPath, "hooks", name),
+ }
+ if isFile(h.path) {
+ data, err := ioutil.ReadFile(h.path)
+ if err != nil {
+ return nil, err
+ }
+ h.IsActive = true
+ h.Content = string(data)
+ } else if isFile(h.path + ".sample") {
+ data, err := ioutil.ReadFile(h.path + ".sample")
+ if err != nil {
+ return nil, err
+ }
+ h.Sample = string(data)
+ }
+ return h, nil
+}
+
+func (h *Hook) Name() string {
+ return h.name
+}
+
+// Update updates hook settings.
+func (h *Hook) Update() error {
+ if len(strings.TrimSpace(h.Content)) == 0 {
+ return os.Remove(h.path)
+ }
+ return ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
+}
+
+// ListHooks returns a list of Git hooks of given repository.
+func ListHooks(repoPath string) (_ []*Hook, err error) {
+ if !isDir(path.Join(repoPath, "hooks")) {
+ return nil, errors.New("hooks path does not exist")
+ }
+
+ hooks := make([]*Hook, len(hookNames))
+ for i, name := range hookNames {
+ hooks[i], err = GetHook(repoPath, name)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return hooks, nil
+}
+
+func (repo *Repository) GetHook(name string) (*Hook, error) {
+ return GetHook(repo.Path, name)
+}
+
+func (repo *Repository) Hooks() ([]*Hook, error) {
+ return ListHooks(repo.Path)
+}
diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go
index 77ae3db0..ed994d48 100644
--- a/modules/git/repo_tag.go
+++ b/modules/git/repo_tag.go
@@ -22,6 +22,9 @@ func (repo *Repository) IsTagExist(tagName string) bool {
// GetTags returns all tags of given repository.
func (repo *Repository) GetTags() ([]string, error) {
+ if gitVer.AtLeast(MustParseVersion("2.0.0")) {
+ return repo.getTagsReversed()
+ }
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l")
if err != nil {
return nil, errors.New(stderr)
@@ -30,6 +33,15 @@ func (repo *Repository) GetTags() ([]string, error) {
return tags[:len(tags)-1], nil
}
+func (repo *Repository) getTagsReversed() ([]string, error) {
+ stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l", "--sort=-v:refname")
+ if err != nil {
+ return nil, errors.New(stderr)
+ }
+ tags := strings.Split(stdout, "\n")
+ return tags[:len(tags)-1], nil
+}
+
func (repo *Repository) CreateTag(tagName, idStr string) error {
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", tagName, idStr)
if err != nil {
diff --git a/modules/git/utils.go b/modules/git/utils.go
index 26eef231..6abbca55 100644
--- a/modules/git/utils.go
+++ b/modules/git/utils.go
@@ -7,6 +7,7 @@ package git
import (
"bytes"
"container/list"
+ "os"
"path/filepath"
"strings"
)
@@ -46,3 +47,23 @@ func RefEndName(refStr string) string {
func filepathFromSHA1(rootdir, sha1 string) string {
return filepath.Join(rootdir, "objects", sha1[:2], sha1[2:])
}
+
+// isDir returns true if given path is a directory,
+// or returns false when it's a file or does not exist.
+func isDir(dir string) bool {
+ f, e := os.Stat(dir)
+ if e != nil {
+ return false
+ }
+ return f.IsDir()
+}
+
+// isFile returns true if given path is a file,
+// or returns false when it's a directory or does not exist.
+func isFile(filePath string) bool {
+ f, e := os.Stat(filePath)
+ if e != nil {
+ return false
+ }
+ return !f.IsDir()
+}
diff --git a/modules/git/version.go b/modules/git/version.go
index 9908d11e..b535521e 100644
--- a/modules/git/version.go
+++ b/modules/git/version.go
@@ -74,6 +74,10 @@ func (v *Version) LessThan(that *Version) bool {
return v.Compare(that) < 0
}
+func (v *Version) AtLeast(that *Version) bool {
+ return v.Compare(that) >= 0
+}
+
// GetVersion returns current Git version installed.
func GetVersion() (*Version, error) {
if gitVer != nil {
diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go
index 92cdfc7d..758792a3 100644
--- a/modules/mailer/mailer.go
+++ b/modules/mailer/mailer.go
@@ -5,7 +5,9 @@
package mailer
import (
+ "crypto/tls"
"fmt"
+ "net"
"net/smtp"
"strings"
@@ -33,7 +35,7 @@ func (m Message) Content() string {
}
// create mail content
- content := "From: " + m.From + "<" + m.User +
+ content := "From: \"" + m.From + "\" <" + m.User +
">\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body
return content
}
@@ -64,6 +66,53 @@ func processMailQueue() {
}
}
+// sendMail allows mail with self-signed certificates.
+func sendMail(hostAddressWithPort string, auth smtp.Auth, from string, recipients []string, msgContent []byte) error {
+ client, err := smtp.Dial(hostAddressWithPort)
+ if err != nil {
+ return err
+ }
+
+ host, _, _ := net.SplitHostPort(hostAddressWithPort)
+ tlsConn := &tls.Config{
+ InsecureSkipVerify: true,
+ ServerName: host,
+ }
+ if err = client.StartTLS(tlsConn); err != nil {
+ return err
+ }
+
+ if auth != nil {
+ if err = client.Auth(auth); err != nil {
+ return err
+ }
+ }
+
+ if err = client.Mail(from); err != nil {
+ return err
+ }
+
+ for _, rec := range recipients {
+ if err = client.Rcpt(rec); err != nil {
+ return err
+ }
+ }
+
+ w, err := client.Data()
+ if err != nil {
+ return err
+ }
+ if _, err = w.Write([]byte(msgContent)); err != nil {
+ return err
+ }
+
+ if err = w.Close(); err != nil {
+ return err
+ }
+
+ return client.Quit()
+}
+
// Direct Send mail message
func Send(msg *Message) (int, error) {
log.Trace("Sending mails to: %s", strings.Join(msg.To, "; "))
@@ -85,7 +134,7 @@ func Send(msg *Message) (int, error) {
num := 0
for _, to := range msg.To {
body := []byte("To: " + to + "\r\n" + content)
- err := smtp.SendMail(setting.MailService.Host, auth, msg.From, []string{to}, body)
+ err := sendMail(setting.MailService.Host, auth, msg.From, []string{to}, body)
if err != nil {
return num, err
}
@@ -96,7 +145,7 @@ func Send(msg *Message) (int, error) {
body := []byte("To: " + strings.Join(msg.To, ";") + "\r\n" + content)
// send to multiple emails in one message
- err := smtp.SendMail(setting.MailService.Host, auth, msg.From, msg.To, body)
+ err := sendMail(setting.MailService.Host, auth, msg.From, msg.To, body)
if err != nil {
return 0, err
} else {
diff --git a/modules/middleware/context.go b/modules/middleware/context.go
index 90716d2c..86e98c90 100644
--- a/modules/middleware/context.go
+++ b/modules/middleware/context.go
@@ -29,7 +29,6 @@ import (
// Context represents context of a request.
type Context struct {
*macaron.Context
- i18n.Locale
Cache cache.Cache
csrf csrf.CSRF
Flash *session.Flash
@@ -76,12 +75,6 @@ type Context struct {
}
}
-// Query querys form parameter.
-func (ctx *Context) Query(name string) string {
- ctx.Req.ParseForm()
- return ctx.Req.Form.Get(name)
-}
-
// HasError returns true if error occurs in form validation.
func (ctx *Context) HasApiError() bool {
hasErr, ok := ctx.Data["HasError"]
@@ -162,7 +155,6 @@ func Contexter() macaron.Handler {
return func(c *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
ctx := &Context{
Context: c,
- Locale: l,
Cache: cache,
csrf: x,
Flash: f,
diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go
index c6250f6d..78af58ea 100644
--- a/modules/middleware/repo.go
+++ b/modules/middleware/repo.go
@@ -308,3 +308,13 @@ func RequireTrueOwner() macaron.Handler {
}
}
}
+
+// GitHookService checks if repsitory Git hooks service has been enabled.
+func GitHookService() macaron.Handler {
+ return func(ctx *Context) {
+ if !setting.Service.EnableGitHooks {
+ ctx.Handle(404, "GitHookService", nil)
+ return
+ }
+ }
+}
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 67e48108..b8fc4dec 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -275,6 +275,7 @@ var Service struct {
LdapAuth bool
ActiveCodeLives int
ResetPwdCodeLives int
+ EnableGitHooks bool
}
func newService() {
@@ -284,6 +285,7 @@ func newService() {
Service.RequireSignInView = Cfg.MustBool("service", "REQUIRE_SIGNIN_VIEW")
Service.EnableCacheAvatar = Cfg.MustBool("service", "ENABLE_CACHE_AVATAR")
Service.EnableReverseProxyAuth = Cfg.MustBool("service", "ENABLE_REVERSE_PROXY_AUTHENTICATION")
+ Service.EnableGitHooks = Cfg.MustBool("service", "ENABLE_GIT_HOOKS")
}
var logLevels = map[string]string{