all repos — captcha @ 797447596cf268e3bf3a1f4459c3977ba6415605

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