|
@@ -0,0 +1,226 @@
|
|
|
|
|
+*TODO(dchest): Add example images and audio.*
|
|
|
|
|
+
|
|
|
|
|
+Package captcha
|
|
|
|
|
+=====================
|
|
|
|
|
+
|
|
|
|
|
+ import "github.com/dchest/captcha"
|
|
|
|
|
+
|
|
|
|
|
+Package captcha implements generation and verification of image and audio
|
|
|
|
|
+CAPTCHAs.
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+Constants
|
|
|
|
|
+---------
|
|
|
|
|
+
|
|
|
|
|
+ const (
|
|
|
|
|
+ // Standard number of digits in captcha.
|
|
|
|
|
+ StdLength = 6
|
|
|
|
|
+ // The number of captchas created that triggers garbage collection used
|
|
|
|
|
+ // by default store.
|
|
|
|
|
+ CollectNum = 100
|
|
|
|
|
+ // Expiration time of captchas used by default store.
|
|
|
|
|
+ Expiration = 10 * 60 // 10 minutes
|
|
|
|
|
+
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ const (
|
|
|
|
|
+ // Standard width and height of a captcha image.
|
|
|
|
|
+ StdWidth = 300
|
|
|
|
|
+ StdHeight = 80
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+Variables
|
|
|
|
|
+---------
|
|
|
|
|
+
|
|
|
|
|
+ var ErrNotFound = os.NewError("captcha with the given id not found")
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+Functions
|
|
|
|
|
+---------
|
|
|
|
|
+
|
|
|
|
|
+### func Collect
|
|
|
|
|
+
|
|
|
|
|
+ func Collect()
|
|
|
|
|
+
|
|
|
|
|
+Collect deletes expired or 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.
|
|
|
|
|
+
|
|
|
|
|
+### func New
|
|
|
|
|
+
|
|
|
|
|
+ func New(length int) (id string)
|
|
|
|
|
+
|
|
|
|
|
+New creates a new captcha of the given length, saves it in the internal
|
|
|
|
|
+storage, and returns its id.
|
|
|
|
|
+
|
|
|
|
|
+### func RandomDigits
|
|
|
|
|
+
|
|
|
|
|
+ func RandomDigits(length int) []byte
|
|
|
|
|
+
|
|
|
|
|
+RandomDigits returns a byte slice of the given length containing random
|
|
|
|
|
+digits in range 0-9.
|
|
|
|
|
+
|
|
|
|
|
+### func Reload
|
|
|
|
|
+
|
|
|
|
|
+ func Reload(id string) bool
|
|
|
|
|
+
|
|
|
|
|
+Reload generates and remembers new digits for the given captcha id. This
|
|
|
|
|
+function returns false if there is no captcha with the given id.
|
|
|
|
|
+
|
|
|
|
|
+After calling this function, the image or audio presented to a user must be
|
|
|
|
|
+refreshed to show the new captcha representation (WriteImage and WriteAudio
|
|
|
|
|
+will write the new one).
|
|
|
|
|
+
|
|
|
|
|
+### func Server
|
|
|
|
|
+
|
|
|
|
|
+ func Server(w, h int) http.Handler
|
|
|
|
|
+
|
|
|
|
|
+Server returns a handler that serves HTTP requests with image or
|
|
|
|
|
+audio representations of captchas. Image dimensions are accepted as
|
|
|
|
|
+arguments. The server decides which captcha to serve based on the last URL
|
|
|
|
|
+path component: file name part must contain a captcha id, file extension —
|
|
|
|
|
+its format (PNG or WAV).
|
|
|
|
|
+
|
|
|
|
|
+For example, for file name "B9QTvDV1RXbVJ3Ac.png" it serves an image captcha
|
|
|
|
|
+with id "B9QTvDV1RXbVJ3Ac", and for "B9QTvDV1RXbVJ3Ac.wav" it serves the
|
|
|
|
|
+same captcha in audio format.
|
|
|
|
|
+
|
|
|
|
|
+To serve an audio captcha as downloadable file, append "?get" to URL.
|
|
|
|
|
+
|
|
|
|
|
+To reload captcha (get a different solution for the same captcha id), append
|
|
|
|
|
+"?reload=x" to URL, where x may be anything (for example, current time or a
|
|
|
|
|
+random number to make browsers refetch an image instead of loading it from
|
|
|
|
|
+cache).
|
|
|
|
|
+
|
|
|
|
|
+### func SetCustomStore
|
|
|
|
|
+
|
|
|
|
|
+ func SetCustomStore(s Store)
|
|
|
|
|
+
|
|
|
|
|
+SetCustomStore sets custom storage for captchas, replacing the default
|
|
|
|
|
+memory store. This function must be called before generating any captchas.
|
|
|
|
|
+
|
|
|
|
|
+### func Verify
|
|
|
|
|
+
|
|
|
|
|
+ func Verify(id string, digits []byte) bool
|
|
|
|
|
+
|
|
|
|
|
+Verify returns true if the given digits are the ones 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 VerifyString
|
|
|
|
|
+
|
|
|
|
|
+ func VerifyString(id string, digits string) bool
|
|
|
|
|
+
|
|
|
|
|
+VerifyString is like Verify, but accepts a string of digits. It removes
|
|
|
|
|
+spaces and commas from the string, but any other characters, apart from
|
|
|
|
|
+digits and listed above, will cause the function to return false.
|
|
|
|
|
+
|
|
|
|
|
+### func WriteAudio
|
|
|
|
|
+
|
|
|
|
|
+ func WriteAudio(w io.Writer, id string) os.Error
|
|
|
|
|
+
|
|
|
|
|
+WriteAudio writes WAV-encoded audio representation of the captcha with the
|
|
|
|
|
+given id.
|
|
|
|
|
+
|
|
|
|
|
+### func WriteImage
|
|
|
|
|
+
|
|
|
|
|
+ func WriteImage(w io.Writer, id string, width, height int) os.Error
|
|
|
|
|
+
|
|
|
|
|
+WriteImage writes PNG-encoded image representation of the captcha with the
|
|
|
|
|
+given id. The image will have the given width and height.
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+Types
|
|
|
|
|
+-----
|
|
|
|
|
+
|
|
|
|
|
+ type Audio struct {
|
|
|
|
|
+ // contains unexported fields
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### func NewAudio
|
|
|
|
|
+
|
|
|
|
|
+ func NewAudio(digits []byte) *Audio
|
|
|
|
|
+
|
|
|
|
|
+NewImage returns a new audio captcha with the given digits, where each digit
|
|
|
|
|
+must be in range 0-9.
|
|
|
|
|
+
|
|
|
|
|
+### func (*Audio) EncodedLen
|
|
|
|
|
+
|
|
|
|
|
+ func (a *Audio) EncodedLen() int
|
|
|
|
|
+
|
|
|
|
|
+EncodedLen returns the length of WAV-encoded audio captcha.
|
|
|
|
|
+
|
|
|
|
|
+### func (*Audio) WriteTo
|
|
|
|
|
+
|
|
|
|
|
+ func (a *Audio) WriteTo(w io.Writer) (n int64, err os.Error)
|
|
|
|
|
+
|
|
|
|
|
+WriteTo writes captcha audio in WAVE format into the given io.Writer, and
|
|
|
|
|
+returns the number of bytes written and an error if any.
|
|
|
|
|
+
|
|
|
|
|
+ type Image struct {
|
|
|
|
|
+ *image.NRGBA
|
|
|
|
|
+ // contains unexported fields
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### func NewImage
|
|
|
|
|
+
|
|
|
|
|
+ func NewImage(digits []byte, width, height int) *Image
|
|
|
|
|
+
|
|
|
|
|
+NewImage returns a new captcha image of the given width and height with the
|
|
|
|
|
+given digits, where each digit must be in range 0-9.
|
|
|
|
|
+
|
|
|
|
|
+### func (*Image) WriteTo
|
|
|
|
|
+
|
|
|
|
|
+ func (img *Image) WriteTo(w io.Writer) (int64, os.Error)
|
|
|
|
|
+
|
|
|
|
|
+WriteTo writes captcha image in PNG format into the given writer.
|
|
|
|
|
+
|
|
|
|
|
+ type Store interface {
|
|
|
|
|
+ // Set sets the digits for the captcha id.
|
|
|
|
|
+ Set(id string, digits []byte)
|
|
|
|
|
+
|
|
|
|
|
+ // Get returns stored digits for the captcha id. Clear indicates
|
|
|
|
|
+ // whether the captcha must be deleted from the store.
|
|
|
|
|
+ Get(id string, clear bool) (digits []byte)
|
|
|
|
|
+
|
|
|
|
|
+ // Collect deletes expired captchas from the store. For custom stores
|
|
|
|
|
+ // this method is not called automatically, it is only wired to the
|
|
|
|
|
+ // package's Collect function. Custom stores must implement their own
|
|
|
|
|
+ // procedure for calling Collect, for example, in Set method.
|
|
|
|
|
+ Collect()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+An object implementing Store interface can be registered with SetCustomStore
|
|
|
|
|
+function to handle storage and retrieval of captcha ids and solutions for
|
|
|
|
|
+them, replacing the default memory store.
|
|
|
|
|
+
|
|
|
|
|
+### func NewMemoryStore
|
|
|
|
|
+
|
|
|
|
|
+ func NewMemoryStore(collectNum int, expiration int64) Store
|
|
|
|
|
+
|
|
|
|
|
+NewMemoryStore returns a new standard memory store for captchas with the
|
|
|
|
|
+given collection threshold and expiration time in seconds. The returned
|
|
|
|
|
+store must be registered with SetCustomStore to replace the default one.
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+Bugs
|
|
|
|
|
+----
|
|
|
|
|
+
|
|
|
|
|
+[Not our bug] Google Chrome 10 plays unsigned 8-bit PCM WAVE
|
|
|
|
|
+audio on Mac with horrible distortions. Issue:
|
|
|
|
|
+http://code.google.com/p/chromium/issues/detail?id=70730.
|
|
|
|
|
+This has been fixed, and version 12 will play them properly.
|
|
|
|
|
+
|
|
|
|
|
+While Image conforms to io.WriterTo interface, its WriteTo
|
|
|
|
|
+method returns 0 instead of the actual bytes written because png.Encode
|
|
|
|
|
+doesn't report this.
|