| @@ -45,7 +45,7 @@ require ( | |||
| github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e // indirect | |||
| github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443 | |||
| github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 | |||
| github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab | |||
| github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df | |||
| github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9 | |||
| github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372 | |||
| github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f | |||
| @@ -113,8 +113,8 @@ github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443 h1:i801KPR7j76u | |||
| github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443/go.mod h1:u+H6rwW+HQwUL+w5uaEJSpIlVZDye1o9MB4Su0JfRfM= | |||
| github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 h1:UYIHS1r0WotqB5cIa0PAiV0m6GzD9rDBcn4alp5JgCw= | |||
| github.com/go-macaron/cache v0.0.0-20151013081102-561735312776/go.mod h1:hHAsZm/oBZVcY+S7qdQL6Vbg5VrXF6RuKGuqsszt3Ok= | |||
| github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab h1:4VFhsA3GE5Wwq1Ymr8KWCmrOWi1wRLEgdj48LPfQjxI= | |||
| github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab/go.mod h1:j9TJ+0nwUOWBvNnm0bheHIPFf3cC62EQo7n7O6PbjZA= | |||
| github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df h1:MdgvtI3Y1u/DHNj7xUGOqAv+KGoTikjy8xQtCm12L78= | |||
| github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df/go.mod h1:j9TJ+0nwUOWBvNnm0bheHIPFf3cC62EQo7n7O6PbjZA= | |||
| github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9 h1:A0QGzY6UHHEil0I2e7C21JenNNG0mmrj5d9SFWTlgr8= | |||
| github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9/go.mod h1:utmMRnVIrXPSfA9MFcpIYKEpKawjKxf62vv62k4707E= | |||
| github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372 h1:acrx8CnDmlKl+BPoOOLEK9Ko+SrWFB5pxRuGkKj4iqo= | |||
| @@ -1,14 +1,10 @@ | |||
| sudo: false | |||
| language: go | |||
| go: | |||
| - 1.3 | |||
| - 1.4 | |||
| - 1.5 | |||
| - tip | |||
| - 1.6.x | |||
| - 1.7.x | |||
| - 1.8.x | |||
| - 1.9.x | |||
| - 1.10.x | |||
| script: go test -v -cover -race | |||
| notifications: | |||
| email: | |||
| - u@gogs.io | |||
| @@ -19,6 +19,7 @@ package captcha | |||
| import ( | |||
| "fmt" | |||
| "html/template" | |||
| "image/color" | |||
| "path" | |||
| "strings" | |||
| @@ -49,6 +50,7 @@ type Captcha struct { | |||
| ChallengeNums int | |||
| Expiration int64 | |||
| CachePrefix string | |||
| ColorPalette color.Palette | |||
| } | |||
| // generate key string | |||
| @@ -61,16 +63,21 @@ func (c *Captcha) genRandChars() string { | |||
| return string(com.RandomCreateBytes(c.ChallengeNums, defaultChars...)) | |||
| } | |||
| // tempalte func for output html | |||
| func (c *Captcha) CreateHtml() template.HTML { | |||
| // CreateHTML outputs HTML for display and fetch new captcha images. | |||
| func (c *Captcha) CreateHTML() template.HTML { | |||
| value, err := c.CreateCaptcha() | |||
| if err != nil { | |||
| panic(fmt.Errorf("fail to create captcha: %v", err)) | |||
| } | |||
| return template.HTML(fmt.Sprintf(`<input type="hidden" name="%s" value="%s"> | |||
| <a class="captcha" href="javascript:"> | |||
| <img onclick="this.src=('%s%s%s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%s%s%s.png"> | |||
| </a>`, c.FieldIdName, value, c.SubURL, c.URLPrefix, value, c.SubURL, c.URLPrefix, value)) | |||
| return template.HTML(fmt.Sprintf(`<input type="hidden" name="%[1]s" value="%[2]s"> | |||
| <a class="captcha" href="javascript:" tabindex="-1"> | |||
| <img onclick="this.src=('%[3]s%[4]s%[2]s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%[3]s%[4]s%[2]s.png"> | |||
| </a>`, c.FieldIdName, value, c.SubURL, c.URLPrefix)) | |||
| } | |||
| // DEPRECATED | |||
| func (c *Captcha) CreateHtml() template.HTML { | |||
| return c.CreateHTML() | |||
| } | |||
| // create a new captcha id | |||
| @@ -139,6 +146,9 @@ type Options struct { | |||
| Expiration int64 | |||
| // Cache key prefix captcha characters. Default is "captcha_". | |||
| CachePrefix string | |||
| // ColorPalette holds a collection of primary colors used for | |||
| // the captcha's text. If not defined, a random color will be generated. | |||
| ColorPalette color.Palette | |||
| } | |||
| func prepareOptions(options []Options) Options { | |||
| @@ -192,6 +202,7 @@ func NewCaptcha(opt Options) *Captcha { | |||
| ChallengeNums: opt.ChallengeNums, | |||
| Expiration: opt.Expiration, | |||
| CachePrefix: opt.CachePrefix, | |||
| ColorPalette: opt.ColorPalette, | |||
| } | |||
| } | |||
| @@ -229,9 +240,10 @@ func Captchaer(options ...Options) macaron.Handler { | |||
| } | |||
| } | |||
| if _, err := NewImage([]byte(chars), cpt.StdWidth, cpt.StdHeight).WriteTo(ctx.Resp); err != nil { | |||
| if _, err := NewImage([]byte(chars), cpt.StdWidth, cpt.StdHeight, cpt.ColorPalette).WriteTo(ctx.Resp); err != nil { | |||
| panic(fmt.Errorf("write captcha: %v", err)) | |||
| } | |||
| ctx.Status(200) | |||
| return | |||
| } | |||
| @@ -265,16 +265,22 @@ func randFloat(from, to float64) float64 { | |||
| return (to-from)*prng.Float64() + from | |||
| } | |||
| func randomPalette() color.Palette { | |||
| func randomPalette(primary color.Palette) 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, | |||
| var prim color.RGBA | |||
| if len(primary) == 0 { | |||
| prim = color.RGBA{ | |||
| uint8(randIntn(129)), | |||
| uint8(randIntn(129)), | |||
| uint8(randIntn(129)), | |||
| 0xFF, | |||
| } | |||
| } else { | |||
| r, g, b, a := primary[randIntn(len(primary)-1)].RGBA() | |||
| prim = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)} | |||
| } | |||
| p[1] = prim | |||
| // Circle colors. | |||
| @@ -285,10 +291,11 @@ func randomPalette() color.Palette { | |||
| } | |||
| // 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 { | |||
| // given digits, where each digit must be in range 0-9. The digit's color is | |||
| // chosen by random from the colorPalette. | |||
| func NewImage(digits []byte, width, height int, colorPalette color.Palette) *Image { | |||
| m := new(Image) | |||
| m.Paletted = image.NewPaletted(image.Rect(0, 0, width, height), randomPalette()) | |||
| m.Paletted = image.NewPaletted(image.Rect(0, 0, width, height), randomPalette(colorPalette)) | |||
| m.calculateSizes(width, height, len(digits)) | |||
| // Randomly position captcha inside the image. | |||
| maxx := width - (m.numWidth+m.dotSize)*len(digits) - m.dotSize | |||
| @@ -124,7 +124,7 @@ github.com/go-macaron/binding | |||
| github.com/go-macaron/cache | |||
| github.com/go-macaron/cache/memcache | |||
| github.com/go-macaron/cache/redis | |||
| # github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab | |||
| # github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df | |||
| github.com/go-macaron/captcha | |||
| # github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9 | |||
| github.com/go-macaron/cors | |||