|
|
@@ -1,3 +1,5 @@
|
|
|
+// Package captcha implements generation and verification of image and audio
|
|
|
+// CAPTCHAs.
|
|
|
package captcha
|
|
|
|
|
|
import (
|
|
|
@@ -24,7 +26,12 @@ const (
|
|
|
var ErrNotFound = os.NewError("captcha with the given id not found")
|
|
|
|
|
|
// globalStore is a shared storage for captchas, generated by New function.
|
|
|
-var globalStore = newStore(StdCollectNum, StdExpiration)
|
|
|
+var globalStore = NewMemoryStore(StdCollectNum, StdExpiration)
|
|
|
+
|
|
|
+// SetCustomStore sets custom storage for captchas.
|
|
|
+func SetCustomStore(s Store) {
|
|
|
+ globalStore = s
|
|
|
+}
|
|
|
|
|
|
// RandomDigits returns a byte slice of the given length containing random
|
|
|
// digits in range 0-9.
|
|
|
@@ -43,7 +50,7 @@ func RandomDigits(length int) []byte {
|
|
|
// storage, and returns its id.
|
|
|
func New(length int) (id string) {
|
|
|
id = uniuri.New()
|
|
|
- globalStore.saveCaptcha(id, RandomDigits(length))
|
|
|
+ globalStore.Set(id, RandomDigits(length))
|
|
|
return
|
|
|
}
|
|
|
|
|
|
@@ -54,18 +61,18 @@ func New(length int) (id string) {
|
|
|
// refreshed to show the new captcha representation (WriteImage and WriteAudio
|
|
|
// will write the new one).
|
|
|
func Reload(id string) bool {
|
|
|
- old := globalStore.getDigits(id)
|
|
|
+ old := globalStore.Get(id, false)
|
|
|
if old == nil {
|
|
|
return false
|
|
|
}
|
|
|
- globalStore.saveCaptcha(id, RandomDigits(len(old)))
|
|
|
+ globalStore.Set(id, RandomDigits(len(old)))
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
// WriteImage writes PNG-encoded image representation of the captcha with the
|
|
|
// given id. The image will have the given width and height.
|
|
|
func WriteImage(w io.Writer, id string, width, height int) os.Error {
|
|
|
- d := globalStore.getDigits(id)
|
|
|
+ d := globalStore.Get(id, false)
|
|
|
if d == nil {
|
|
|
return ErrNotFound
|
|
|
}
|
|
|
@@ -76,7 +83,7 @@ func WriteImage(w io.Writer, id string, width, height int) os.Error {
|
|
|
// WriteAudio writes WAV-encoded audio representation of the captcha with the
|
|
|
// given id.
|
|
|
func WriteAudio(w io.Writer, id string) os.Error {
|
|
|
- d := globalStore.getDigits(id)
|
|
|
+ d := globalStore.Get(id, false)
|
|
|
if d == nil {
|
|
|
return ErrNotFound
|
|
|
}
|
|
|
@@ -93,7 +100,7 @@ func Verify(id string, digits []byte) bool {
|
|
|
if digits == nil || len(digits) == 0 {
|
|
|
return false
|
|
|
}
|
|
|
- reald := globalStore.getDigitsClear(id)
|
|
|
+ reald := globalStore.Get(id, true)
|
|
|
if reald == nil {
|
|
|
return false
|
|
|
}
|
|
|
@@ -128,7 +135,7 @@ func VerifyString(id string, digits string) bool {
|
|
|
//
|
|
|
// Collection is launched in a new goroutine.
|
|
|
func Collect() {
|
|
|
- go globalStore.collect()
|
|
|
+ go globalStore.Collect()
|
|
|
}
|
|
|
|
|
|
type captchaHandler struct {
|
|
|
@@ -171,7 +178,7 @@ func (h *captchaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
//err = WriteAudio(buf, id)
|
|
|
//XXX(dchest) Workaround for Chrome: it wants content-length,
|
|
|
//or else will start playing NOT from the beginning.
|
|
|
- d := globalStore.getDigits(id)
|
|
|
+ d := globalStore.Get(id, false)
|
|
|
if d == nil {
|
|
|
err = ErrNotFound
|
|
|
} else {
|