all repos — captcha @ d36aa1f342df1c83a78ffb1b37d3760eea13c626

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

captcha.go (view raw)

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