| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- package captcha
- import (
- "bytes"
- "crypto/rand"
- "github.com/dchest/uniuri"
- "io"
- "os"
- )
- // Standard number of numbers in captcha
- const StdLength = 6
- var globalStore = newStore()
- // randomNumbers return a byte slice of the given length containing random
- // numbers in range 0-9.
- func randomNumbers(length int) []byte {
- n := make([]byte, length)
- if _, err := io.ReadFull(rand.Reader, n); err != nil {
- panic(err)
- }
- for i := range n {
- n[i] %= 10
- }
- return n
- }
- // New creates a new captcha of the given length, saves it in the internal
- // storage, and returns its id.
- func New(length int) (id string) {
- id = uniuri.New()
- globalStore.saveCaptcha(id, randomNumbers(length))
- return
- }
- // Reload generates new numbers for the given captcha id. This function does
- // nothing if there is no captcha with the given id.
- //
- // After calling this function, the image presented to a user must be refreshed
- // to show the new captcha (WriteImage will write the new one).
- func Reload(id string) {
- oldns := globalStore.getNumbers(id)
- if oldns == nil {
- return
- }
- globalStore.saveCaptcha(id, randomNumbers(len(oldns)))
- }
- // WriteImage writes PNG-encoded captcha image of the given width and height
- // with the given captcha id into the io.Writer.
- func WriteImage(w io.Writer, id string, width, height int) os.Error {
- ns := globalStore.getNumbers(id)
- if ns == nil {
- return os.NewError("captcha id not found")
- }
- return NewImage(ns, width, height).PNGEncode(w)
- }
- // Verify returns true if the given numbers are the numbers that were used to
- // create the given captcha id.
- //
- // The function deletes the captcha with the given id from the internal
- // storage, so that the same captcha can't be verified anymore.
- func Verify(id string, numbers []byte) bool {
- realns := globalStore.getNumbersClear(id)
- if realns == nil {
- return false
- }
- return bytes.Equal(numbers, realns)
- }
- // Collect deletes expired and used captchas from the internal
- // storage. It is called automatically by New function every CollectNum
- // generated captchas, but still exported to enable freeing memory manually if
- // needed.
- //
- // Collection is launched in a new goroutine, so this function returns
- // immediately.
- func Collect() {
- go globalStore.collect()
- }
|