summaryrefslogtreecommitdiffstats
path: root/modules/captcha
diff options
context:
space:
mode:
Diffstat (limited to 'modules/captcha')
-rw-r--r--modules/captcha/captcha.go201
-rw-r--r--modules/captcha/image.go487
-rw-r--r--modules/captcha/image_test.go42
-rw-r--r--modules/captcha/siprng.go267
-rw-r--r--modules/captcha/siprng_test.go23
5 files changed, 0 insertions, 1020 deletions
diff --git a/modules/captcha/captcha.go b/modules/captcha/captcha.go
deleted file mode 100644
index e43e09dc59..0000000000
--- a/modules/captcha/captcha.go
+++ /dev/null
@@ -1,201 +0,0 @@
-// 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 captcha a middleware that provides captcha service for Macaron.
-package captcha
-
-import (
- "fmt"
- "html/template"
- "net/http"
- "path"
- "strings"
-
- "github.com/Unknwon/macaron"
-
- "github.com/gogits/cache"
-
- "github.com/gogits/gogs/modules/base"
- "github.com/gogits/gogs/modules/log"
-)
-
-var (
- defaultChars = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
-)
-
-const (
- // default captcha attributes
- challengeNums = 6
- expiration = 600
- fieldIdName = "captcha_id"
- fieldCaptchaName = "captcha"
- cachePrefix = "captcha_"
- defaultURLPrefix = "/captcha/"
-)
-
-// Captcha struct
-type Captcha struct {
- store cache.Cache
-
- // url prefix for captcha image
- URLPrefix string
-
- // specify captcha id input field name
- FieldIdName string
- // specify captcha result input field name
- FieldCaptchaName string
-
- // captcha image width and height
- StdWidth int
- StdHeight int
-
- // captcha chars nums
- ChallengeNums int
-
- // captcha expiration seconds
- Expiration int64
-
- // cache key prefix
- CachePrefix string
-}
-
-// generate key string
-func (c *Captcha) key(id string) string {
- return c.CachePrefix + id
-}
-
-// generate rand chars with default chars
-func (c *Captcha) genRandChars() []byte {
- return base.RandomCreateBytes(c.ChallengeNums, defaultChars...)
-}
-
-// beego filter handler for serve captcha image
-func (c *Captcha) Handler(ctx *macaron.Context) {
- var chars []byte
-
- id := path.Base(ctx.Req.RequestURI)
- if i := strings.Index(id, "."); i != -1 {
- id = id[:i]
- }
-
- key := c.key(id)
-
- if v, ok := c.store.Get(key).([]byte); ok {
- chars = v
- } else {
- ctx.Status(404)
- ctx.Write([]byte("captcha not found"))
- return
- }
-
- // reload captcha
- if len(ctx.Query("reload")) > 0 {
- chars = c.genRandChars()
- if err := c.store.Put(key, chars, c.Expiration); err != nil {
- ctx.Status(500)
- ctx.Write([]byte("captcha reload error"))
- log.Error(4, "Reload Create Captcha Error: %v", err)
- return
- }
- }
-
- img := NewImage(chars, c.StdWidth, c.StdHeight)
- if _, err := img.WriteTo(ctx.RW()); err != nil {
- log.Error(4, "Write Captcha Image Error: %v", err)
- }
-}
-
-// tempalte func for output html
-func (c *Captcha) CreateCaptchaHtml() template.HTML {
- value, err := c.CreateCaptcha()
- if err != nil {
- log.Error(4, "Create Captcha Error: %v", err)
- return ""
- }
-
- // create html
- return template.HTML(fmt.Sprintf(`<input type="hidden" name="%s" value="%s">`+
- `<a class="captcha" href="javascript:">`+
- `<img onclick="this.src=('%s%s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%s%s.png">`+
- `</a>`, c.FieldIdName, value, c.URLPrefix, value, c.URLPrefix, value))
-}
-
-// create a new captcha id
-func (c *Captcha) CreateCaptcha() (string, error) {
- // generate captcha id
- id := string(base.RandomCreateBytes(15))
-
- // get the captcha chars
- chars := c.genRandChars()
-
- // save to store
- if err := c.store.Put(c.key(id), chars, c.Expiration); err != nil {
- return "", err
- }
-
- return id, nil
-}
-
-// verify from a request
-func (c *Captcha) VerifyReq(req *http.Request) bool {
- req.ParseForm()
- return c.Verify(req.Form.Get(c.FieldIdName), req.Form.Get(c.FieldCaptchaName))
-}
-
-// direct verify id and challenge string
-func (c *Captcha) Verify(id string, challenge string) (success bool) {
- if len(challenge) == 0 || len(id) == 0 {
- return
- }
-
- var chars []byte
-
- key := c.key(id)
-
- if v, ok := c.store.Get(key).([]byte); ok && len(v) == len(challenge) {
- chars = v
- } else {
- return
- }
-
- defer func() {
- // finally remove it
- c.store.Delete(key)
- }()
-
- // verify challenge
- for i, c := range chars {
- if c != challenge[i]-48 {
- return
- }
- }
-
- return true
-}
-
-// create a new captcha.Captcha
-func NewCaptcha(urlPrefix string, store cache.Cache) *Captcha {
- cpt := &Captcha{}
- cpt.store = store
- cpt.FieldIdName = fieldIdName
- cpt.FieldCaptchaName = fieldCaptchaName
- cpt.ChallengeNums = challengeNums
- cpt.Expiration = expiration
- cpt.CachePrefix = cachePrefix
- cpt.StdWidth = stdWidth
- cpt.StdHeight = stdHeight
-
- if len(urlPrefix) == 0 {
- urlPrefix = defaultURLPrefix
- }
-
- if urlPrefix[len(urlPrefix)-1] != '/' {
- urlPrefix += "/"
- }
-
- cpt.URLPrefix = urlPrefix
-
- base.TemplateFuncs["CreateCaptcha"] = cpt.CreateCaptchaHtml
- return cpt
-}
diff --git a/modules/captcha/image.go b/modules/captcha/image.go
deleted file mode 100644
index c9972ba2c3..0000000000
--- a/modules/captcha/image.go
+++ /dev/null
@@ -1,487 +0,0 @@
-// 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 captcha
-
-import (
- "bytes"
- "image"
- "image/color"
- "image/png"
- "io"
- "math"
-)
-
-const (
- fontWidth = 11
- fontHeight = 18
- blackChar = 1
-
- // Standard width and height of a captcha image.
- stdWidth = 240
- stdHeight = 80
- // Maximum absolute skew factor of a single digit.
- maxSkew = 0.7
- // Number of background circles.
- circleCount = 20
-)
-
-var font = [][]byte{
- { // 0
- 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
- 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0,
- 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
- },
- { // 1
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- },
- { // 2
- 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0,
- 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- },
- { // 3
- 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- },
- { // 4
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
- 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
- 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
- 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- },
- { // 5
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- },
- { // 6
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0,
- 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
- 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0,
- 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
- 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
- },
- { // 7
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- },
- { // 8
- 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0,
- 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0,
- 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
- 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
- },
- { // 9
- 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
- 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0,
- 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
- 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- },
-}
-
-type Image struct {
- *image.Paletted
- numWidth int
- numHeight int
- dotSize int
-}
-
-var prng = &siprng{}
-
-// randIntn returns a pseudorandom non-negative int in range [0, n).
-func randIntn(n int) int {
- return prng.Intn(n)
-}
-
-// randInt returns a pseudorandom int in range [from, to].
-func randInt(from, to int) int {
- return prng.Intn(to+1-from) + from
-}
-
-// randFloat returns a pseudorandom float64 in range [from, to].
-func randFloat(from, to float64) float64 {
- return (to-from)*prng.Float64() + from
-}
-
-func randomPalette() color.Palette {
- p := make([]color.Color, circleCount+1)
- // Transparent color.
- p[0] = color.RGBA{0xFF, 0xFF, 0xFF, 0x00}
- // Primary color.
- prim := color.RGBA{
- uint8(randIntn(129)),
- uint8(randIntn(129)),
- uint8(randIntn(129)),
- 0xFF,
- }
- p[1] = prim
- // Circle colors.
- for i := 2; i <= circleCount; i++ {
- p[i] = randomBrightness(prim, 255)
- }
- return p
-}
-
-// NewImage returns a new captcha image of the given width and height with the
-// given digits, where each digit must be in range 0-9.
-func NewImage(digits []byte, width, height int) *Image {
- m := new(Image)
- m.Paletted = image.NewPaletted(image.Rect(0, 0, width, height), randomPalette())
- m.calculateSizes(width, height, len(digits))
- // Randomly position captcha inside the image.
- maxx := width - (m.numWidth+m.dotSize)*len(digits) - m.dotSize
- maxy := height - m.numHeight - m.dotSize*2
- var border int
- if width > height {
- border = height / 5
- } else {
- border = width / 5
- }
- x := randInt(border, maxx-border)
- y := randInt(border, maxy-border)
- // Draw digits.
- for _, n := range digits {
- m.drawDigit(font[n], x, y)
- x += m.numWidth + m.dotSize
- }
- // Draw strike-through line.
- m.strikeThrough()
- // Apply wave distortion.
- m.distort(randFloat(5, 10), randFloat(100, 200))
- // Fill image with random circles.
- m.fillWithCircles(circleCount, m.dotSize)
- return m
-}
-
-// encodedPNG encodes an image to PNG and returns
-// the result as a byte slice.
-func (m *Image) encodedPNG() []byte {
- var buf bytes.Buffer
- if err := png.Encode(&buf, m.Paletted); err != nil {
- panic(err.Error())
- }
- return buf.Bytes()
-}
-
-// WriteTo writes captcha image in PNG format into the given writer.
-func (m *Image) WriteTo(w io.Writer) (int64, error) {
- n, err := w.Write(m.encodedPNG())
- return int64(n), err
-}
-
-func (m *Image) calculateSizes(width, height, ncount int) {
- // Goal: fit all digits inside the image.
- var border int
- if width > height {
- border = height / 4
- } else {
- border = width / 4
- }
- // Convert everything to floats for calculations.
- w := float64(width - border*2)
- h := float64(height - border*2)
- // fw takes into account 1-dot spacing between digits.
- fw := float64(fontWidth + 1)
- fh := float64(fontHeight)
- nc := float64(ncount)
- // Calculate the width of a single digit taking into account only the
- // width of the image.
- nw := w / nc
- // Calculate the height of a digit from this width.
- nh := nw * fh / fw
- // Digit too high?
- if nh > h {
- // Fit digits based on height.
- nh = h
- nw = fw / fh * nh
- }
- // Calculate dot size.
- m.dotSize = int(nh / fh)
- // Save everything, making the actual width smaller by 1 dot to account
- // for spacing between digits.
- m.numWidth = int(nw) - m.dotSize
- m.numHeight = int(nh)
-}
-
-func (m *Image) drawHorizLine(fromX, toX, y int, colorIdx uint8) {
- for x := fromX; x <= toX; x++ {
- m.SetColorIndex(x, y, colorIdx)
- }
-}
-
-func (m *Image) drawCircle(x, y, radius int, colorIdx uint8) {
- f := 1 - radius
- dfx := 1
- dfy := -2 * radius
- xo := 0
- yo := radius
-
- m.SetColorIndex(x, y+radius, colorIdx)
- m.SetColorIndex(x, y-radius, colorIdx)
- m.drawHorizLine(x-radius, x+radius, y, colorIdx)
-
- for xo < yo {
- if f >= 0 {
- yo--
- dfy += 2
- f += dfy
- }
- xo++
- dfx += 2
- f += dfx
- m.drawHorizLine(x-xo, x+xo, y+yo, colorIdx)
- m.drawHorizLine(x-xo, x+xo, y-yo, colorIdx)
- m.drawHorizLine(x-yo, x+yo, y+xo, colorIdx)
- m.drawHorizLine(x-yo, x+yo, y-xo, colorIdx)
- }
-}
-
-func (m *Image) fillWithCircles(n, maxradius int) {
- maxx := m.Bounds().Max.X
- maxy := m.Bounds().Max.Y
- for i := 0; i < n; i++ {
- colorIdx := uint8(randInt(1, circleCount-1))
- r := randInt(1, maxradius)
- m.drawCircle(randInt(r, maxx-r), randInt(r, maxy-r), r, colorIdx)
- }
-}
-
-func (m *Image) strikeThrough() {
- maxx := m.Bounds().Max.X
- maxy := m.Bounds().Max.Y
- y := randInt(maxy/3, maxy-maxy/3)
- amplitude := randFloat(5, 20)
- period := randFloat(80, 180)
- dx := 2.0 * math.Pi / period
- for x := 0; x < maxx; x++ {
- xo := amplitude * math.Cos(float64(y)*dx)
- yo := amplitude * math.Sin(float64(x)*dx)
- for yn := 0; yn < m.dotSize; yn++ {
- r := randInt(0, m.dotSize)
- m.drawCircle(x+int(xo), y+int(yo)+(yn*m.dotSize), r/2, 1)
- }
- }
-}
-
-func (m *Image) drawDigit(digit []byte, x, y int) {
- skf := randFloat(-maxSkew, maxSkew)
- xs := float64(x)
- r := m.dotSize / 2
- y += randInt(-r, r)
- for yo := 0; yo < fontHeight; yo++ {
- for xo := 0; xo < fontWidth; xo++ {
- if digit[yo*fontWidth+xo] != blackChar {
- continue
- }
- m.drawCircle(x+xo*m.dotSize, y+yo*m.dotSize, r, 1)
- }
- xs += skf
- x = int(xs)
- }
-}
-
-func (m *Image) distort(amplude float64, period float64) {
- w := m.Bounds().Max.X
- h := m.Bounds().Max.Y
-
- oldm := m.Paletted
- newm := image.NewPaletted(image.Rect(0, 0, w, h), oldm.Palette)
-
- dx := 2.0 * math.Pi / period
- for x := 0; x < w; x++ {
- for y := 0; y < h; y++ {
- xo := amplude * math.Sin(float64(y)*dx)
- yo := amplude * math.Cos(float64(x)*dx)
- newm.SetColorIndex(x, y, oldm.ColorIndexAt(x+int(xo), y+int(yo)))
- }
- }
- m.Paletted = newm
-}
-
-func randomBrightness(c color.RGBA, max uint8) color.RGBA {
- minc := min3(c.R, c.G, c.B)
- maxc := max3(c.R, c.G, c.B)
- if maxc > max {
- return c
- }
- n := randIntn(int(max-maxc)) - int(minc)
- return color.RGBA{
- uint8(int(c.R) + n),
- uint8(int(c.G) + n),
- uint8(int(c.B) + n),
- uint8(c.A),
- }
-}
-
-func min3(x, y, z uint8) (m uint8) {
- m = x
- if y < m {
- m = y
- }
- if z < m {
- m = z
- }
- return
-}
-
-func max3(x, y, z uint8) (m uint8) {
- m = x
- if y > m {
- m = y
- }
- if z > m {
- m = z
- }
- return
-}
diff --git a/modules/captcha/image_test.go b/modules/captcha/image_test.go
deleted file mode 100644
index 35810d0c72..0000000000
--- a/modules/captcha/image_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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 captcha
-
-import (
- "testing"
-
- "github.com/gogits/gogs/modules/base"
-)
-
-type byteCounter struct {
- n int64
-}
-
-func (bc *byteCounter) Write(b []byte) (int, error) {
- bc.n += int64(len(b))
- return len(b), nil
-}
-
-func BenchmarkNewImage(b *testing.B) {
- b.StopTimer()
- d := base.RandomCreateBytes(challengeNums, defaultChars...)
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- NewImage(d, stdWidth, stdHeight)
- }
-}
-
-func BenchmarkImageWriteTo(b *testing.B) {
- b.StopTimer()
- d := base.RandomCreateBytes(challengeNums, defaultChars...)
- b.StartTimer()
- counter := &byteCounter{}
- for i := 0; i < b.N; i++ {
- img := NewImage(d, stdWidth, stdHeight)
- img.WriteTo(counter)
- b.SetBytes(counter.n)
- counter.n = 0
- }
-}
diff --git a/modules/captcha/siprng.go b/modules/captcha/siprng.go
deleted file mode 100644
index c059b9f7bf..0000000000
--- a/modules/captcha/siprng.go
+++ /dev/null
@@ -1,267 +0,0 @@
-// 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 captcha
-
-import (
- "crypto/rand"
- "encoding/binary"
- "io"
- "sync"
-)
-
-// siprng is PRNG based on SipHash-2-4.
-type siprng struct {
- mu sync.Mutex
- k0, k1, ctr uint64
-}
-
-// siphash implements SipHash-2-4, accepting a uint64 as a message.
-func siphash(k0, k1, m uint64) uint64 {
- // Initialization.
- v0 := k0 ^ 0x736f6d6570736575
- v1 := k1 ^ 0x646f72616e646f6d
- v2 := k0 ^ 0x6c7967656e657261
- v3 := k1 ^ 0x7465646279746573
- t := uint64(8) << 56
-
- // Compression.
- v3 ^= m
-
- // Round 1.
- v0 += v1
- v1 = v1<<13 | v1>>(64-13)
- v1 ^= v0
- v0 = v0<<32 | v0>>(64-32)
-
- v2 += v3
- v3 = v3<<16 | v3>>(64-16)
- v3 ^= v2
-
- v0 += v3
- v3 = v3<<21 | v3>>(64-21)
- v3 ^= v0
-
- v2 += v1
- v1 = v1<<17 | v1>>(64-17)
- v1 ^= v2
- v2 = v2<<32 | v2>>(64-32)
-
- // Round 2.
- v0 += v1
- v1 = v1<<13 | v1>>(64-13)
- v1 ^= v0
- v0 = v0<<32 | v0>>(64-32)
-
- v2 += v3
- v3 = v3<<16 | v3>>(64-16)
- v3 ^= v2
-
- v0 += v3
- v3 = v3<<21 | v3>>(64-21)
- v3 ^= v0
-
- v2 += v1
- v1 = v1<<17 | v1>>(64-17)
- v1 ^= v2
- v2 = v2<<32 | v2>>(64-32)
-
- v0 ^= m
-
- // Compress last block.
- v3 ^= t
-
- // Round 1.
- v0 += v1
- v1 = v1<<13 | v1>>(64-13)
- v1 ^= v0
- v0 = v0<<32 | v0>>(64-32)
-
- v2 += v3
- v3 = v3<<16 | v3>>(64-16)
- v3 ^= v2
-
- v0 += v3
- v3 = v3<<21 | v3>>(64-21)
- v3 ^= v0
-
- v2 += v1
- v1 = v1<<17 | v1>>(64-17)
- v1 ^= v2
- v2 = v2<<32 | v2>>(64-32)
-
- // Round 2.
- v0 += v1
- v1 = v1<<13 | v1>>(64-13)
- v1 ^= v0
- v0 = v0<<32 | v0>>(64-32)
-
- v2 += v3
- v3 = v3<<16 | v3>>(64-16)
- v3 ^= v2
-
- v0 += v3
- v3 = v3<<21 | v3>>(64-21)
- v3 ^= v0
-
- v2 += v1
- v1 = v1<<17 | v1>>(64-17)
- v1 ^= v2
- v2 = v2<<32 | v2>>(64-32)
-
- v0 ^= t
-
- // Finalization.
- v2 ^= 0xff
-
- // Round 1.
- v0 += v1
- v1 = v1<<13 | v1>>(64-13)
- v1 ^= v0
- v0 = v0<<32 | v0>>(64-32)
-
- v2 += v3
- v3 = v3<<16 | v3>>(64-16)
- v3 ^= v2
-
- v0 += v3
- v3 = v3<<21 | v3>>(64-21)
- v3 ^= v0
-
- v2 += v1
- v1 = v1<<17 | v1>>(64-17)
- v1 ^= v2
- v2 = v2<<32 | v2>>(64-32)
-
- // Round 2.
- v0 += v1
- v1 = v1<<13 | v1>>(64-13)
- v1 ^= v0
- v0 = v0<<32 | v0>>(64-32)
-
- v2 += v3
- v3 = v3<<16 | v3>>(64-16)
- v3 ^= v2
-
- v0 += v3
- v3 = v3<<21 | v3>>(64-21)
- v3 ^= v0
-
- v2 += v1
- v1 = v1<<17 | v1>>(64-17)
- v1 ^= v2
- v2 = v2<<32 | v2>>(64-32)
-
- // Round 3.
- v0 += v1
- v1 = v1<<13 | v1>>(64-13)
- v1 ^= v0
- v0 = v0<<32 | v0>>(64-32)
-
- v2 += v3
- v3 = v3<<16 | v3>>(64-16)
- v3 ^= v2
-
- v0 += v3
- v3 = v3<<21 | v3>>(64-21)
- v3 ^= v0
-
- v2 += v1
- v1 = v1<<17 | v1>>(64-17)
- v1 ^= v2
- v2 = v2<<32 | v2>>(64-32)
-
- // Round 4.
- v0 += v1
- v1 = v1<<13 | v1>>(64-13)
- v1 ^= v0
- v0 = v0<<32 | v0>>(64-32)
-
- v2 += v3
- v3 = v3<<16 | v3>>(64-16)
- v3 ^= v2
-
- v0 += v3
- v3 = v3<<21 | v3>>(64-21)
- v3 ^= v0
-
- v2 += v1
- v1 = v1<<17 | v1>>(64-17)
- v1 ^= v2
- v2 = v2<<32 | v2>>(64-32)
-
- return v0 ^ v1 ^ v2 ^ v3
-}
-
-// rekey sets a new PRNG key, which is read from crypto/rand.
-func (p *siprng) rekey() {
- var k [16]byte
- if _, err := io.ReadFull(rand.Reader, k[:]); err != nil {
- panic(err.Error())
- }
- p.k0 = binary.LittleEndian.Uint64(k[0:8])
- p.k1 = binary.LittleEndian.Uint64(k[8:16])
- p.ctr = 1
-}
-
-// Uint64 returns a new pseudorandom uint64.
-// It rekeys PRNG on the first call and every 64 MB of generated data.
-func (p *siprng) Uint64() uint64 {
- p.mu.Lock()
- if p.ctr == 0 || p.ctr > 8*1024*1024 {
- p.rekey()
- }
- v := siphash(p.k0, p.k1, p.ctr)
- p.ctr++
- p.mu.Unlock()
- return v
-}
-
-func (p *siprng) Int63() int64 {
- return int64(p.Uint64() & 0x7fffffffffffffff)
-}
-
-func (p *siprng) Uint32() uint32 {
- return uint32(p.Uint64())
-}
-
-func (p *siprng) Int31() int32 {
- return int32(p.Uint32() & 0x7fffffff)
-}
-
-func (p *siprng) Intn(n int) int {
- if n <= 0 {
- panic("invalid argument to Intn")
- }
- if n <= 1<<31-1 {
- return int(p.Int31n(int32(n)))
- }
- return int(p.Int63n(int64(n)))
-}
-
-func (p *siprng) Int63n(n int64) int64 {
- if n <= 0 {
- panic("invalid argument to Int63n")
- }
- max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
- v := p.Int63()
- for v > max {
- v = p.Int63()
- }
- return v % n
-}
-
-func (p *siprng) Int31n(n int32) int32 {
- if n <= 0 {
- panic("invalid argument to Int31n")
- }
- max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
- v := p.Int31()
- for v > max {
- v = p.Int31()
- }
- return v % n
-}
-
-func (p *siprng) Float64() float64 { return float64(p.Int63()) / (1 << 63) }
diff --git a/modules/captcha/siprng_test.go b/modules/captcha/siprng_test.go
deleted file mode 100644
index 3b10fe58bf..0000000000
--- a/modules/captcha/siprng_test.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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 captcha
-
-import "testing"
-
-func TestSiphash(t *testing.T) {
- good := uint64(0xe849e8bb6ffe2567)
- cur := siphash(0, 0, 0)
- if cur != good {
- t.Fatalf("siphash: expected %x, got %x", good, cur)
- }
-}
-
-func BenchmarkSiprng(b *testing.B) {
- b.SetBytes(8)
- p := &siprng{}
- for i := 0; i < b.N; i++ {
- p.Uint64()
- }
-}