all repos — captcha @ ebb75a0b6ca0591c2ca8898fa0d60c5e6adfa548

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

server.go (view raw)

 1package captcha
 2
 3import (
 4	"http"
 5	"os"
 6	"path"
 7	"strconv"
 8)
 9
10type captchaHandler struct {
11	imgWidth  int
12	imgHeight int
13}
14
15// Server returns a handler that serves HTTP requests with image or
16// audio representations of captchas. Image dimensions are accepted as
17// arguments. The server decides which captcha to serve based on the last URL
18// path component: file name part must contain a captcha id, file extension —
19// its format (PNG or WAV).
20//
21// For example, for file name "LBm5vMjHDtdUfaWYXiQX.png" it serves an image captcha
22// with id "LBm5vMjHDtdUfaWYXiQX", and for "LBm5vMjHDtdUfaWYXiQX.wav" it serves the
23// same captcha in audio format.
24//
25// To serve a captcha as a downloadable file, the URL must be constructed in
26// such a way as if the file to serve is in the "download" subdirectory:
27// "/download/LBm5vMjHDtdUfaWYXiQX.wav".
28//
29// To reload captcha (get a different solution for the same captcha id), append
30// "?reload=x" to URL, where x may be anything (for example, current time or a
31// random number to make browsers refetch an image instead of loading it from
32// cache).
33func Server(imgWidth, imgHeight int) http.Handler { 
34	return &captchaHandler{imgWidth, imgHeight}
35}
36
37func (h *captchaHandler) serve(w http.ResponseWriter, id, ext string, download bool) os.Error {
38	if download {
39		w.Header().Set("Content-Type", "application/octet-stream")
40	}
41	switch ext {
42	case ".png":
43		if !download {
44			w.Header().Set("Content-Type", "image/png")
45		}
46		return WriteImage(w, id, h.imgWidth, h.imgHeight)
47	case ".wav":
48		//XXX(dchest) Workaround for Chrome: it wants content-length,
49		//or else will start playing NOT from the beginning.
50		//Filed issue: http://code.google.com/p/chromium/issues/detail?id=80565
51		d := globalStore.Get(id, false)
52		if d == nil {
53			return ErrNotFound
54		}
55		a := NewAudio(d)
56		if !download {
57			w.Header().Set("Content-Type", "audio/x-wav")
58		}
59		w.Header().Set("Content-Length", strconv.Itoa(a.EncodedLen()))
60		_, err := a.WriteTo(w)
61		return err
62	}
63	return ErrNotFound
64}
65
66func (h *captchaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
67	dir, file := path.Split(r.URL.Path)
68	ext := path.Ext(file)
69	id := file[:len(file)-len(ext)]
70	if ext == "" || id == "" {
71		http.NotFound(w, r)
72		return
73	}
74	if r.FormValue("reload") != "" {
75		Reload(id)
76	}
77	download := path.Base(dir) == "download"
78	if h.serve(w, id, ext, download) == ErrNotFound {
79		http.NotFound(w, r)
80	}
81	// Ignore other errors.
82}