all repos — captcha @ 9de0d066b9199eb378005dfef151c0dcfb81da7f

Go package captcha implements generation and verification of image and audio CAPTCHAs.

captcha.go (view raw)

 1package captcha
 2
 3import (
 4	"bytes"
 5	"crypto/rand"
 6	"github.com/dchest/uniuri"
 7	"io"
 8	"os"
 9)
10
11// Standard number of digits in captcha.
12const StdLength = 6
13
14var ErrNotFound = os.NewError("captcha with the given id not found")
15
16var globalStore = newStore()
17
18// RandomDigits returns a byte slice of the given length containing random
19// digits in range 0-9.
20func RandomDigits(length int) []byte {
21	d := make([]byte, length)
22	if _, err := io.ReadFull(rand.Reader, d); err != nil {
23		panic(err)
24	}
25	for i := range d {
26		d[i] %= 10
27	}
28	return d
29}
30
31// New creates a new captcha of the given length, saves it in the internal
32// storage, and returns its id.
33func New(length int) (id string) {
34	id = uniuri.New()
35	globalStore.saveCaptcha(id, RandomDigits(length))
36	return
37}
38
39// Reload generates and remembers new digits for the given captcha id.  This
40// function returns false if there is no captcha with the given id.
41//
42// After calling this function, the image or audio presented to a user must be
43// refreshed to show the new captcha representation (WriteImage and WriteAudio
44// will write the new one).
45func Reload(id string) bool {
46	old := globalStore.getDigits(id)
47	if old == nil {
48		return false
49	}
50	globalStore.saveCaptcha(id, RandomDigits(len(old)))
51	return true
52}
53
54// WriteImage writes PNG-encoded image representation of the captcha with the
55// given id. The image will have the given width and height.
56func WriteImage(w io.Writer, id string, width, height int) os.Error {
57	d := globalStore.getDigits(id)
58	if d == nil {
59		return ErrNotFound
60	}
61	_, err := NewImage(d, width, height).WriteTo(w)
62	return err
63}
64
65// WriteAudio writes WAV-encoded audio representation of the captcha with the
66// given id.
67func WriteAudio(w io.Writer, id string) os.Error {
68	d := globalStore.getDigits(id)
69	if d == nil {
70		return ErrNotFound
71	}
72	_, err := NewAudio(d).WriteTo(w)
73	return err
74}
75
76// Verify returns true if the given digits are the ones that were used to
77// create the given captcha id.
78// 
79// The function deletes the captcha with the given id from the internal
80// storage, so that the same captcha can't be verified anymore.
81func Verify(id string, digits []byte) bool {
82	reald := globalStore.getDigitsClear(id)
83	if reald == nil {
84		return false
85	}
86	return bytes.Equal(digits, reald)
87}
88
89// Collect deletes expired and used captchas from the internal
90// storage. It is called automatically by New function every CollectNum
91// generated captchas, but still exported to enable freeing memory manually if
92// needed.
93//
94// Collection is launched in a new goroutine, so this function returns
95// immediately.
96func Collect() {
97	go globalStore.collect()
98}