You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

captcha.go 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package main
  2. import (
  3. "github.com/dchest/captcha"
  4. "github.com/gorilla/csrf"
  5. "log"
  6. "net/http"
  7. )
  8. func beginCaptcha(rw http.ResponseWriter, req *http.Request, body string, replyTo string) {
  9. session, err := store.New(req, sessionName)
  10. if err != nil {
  11. log.Printf("Unable to get session: %s", err.Error())
  12. rw.Header().Add("Location", "failure")
  13. rw.WriteHeader(http.StatusSeeOther)
  14. return
  15. }
  16. session.Values[bodyKey] = body
  17. session.Values[replyToKey] = replyTo
  18. err = session.Save(req, rw)
  19. if err != nil {
  20. log.Printf("Unable to save session: %s", err.Error())
  21. rw.Header().Add("Location", "failure")
  22. rw.WriteHeader(http.StatusSeeOther)
  23. return
  24. }
  25. rw.Header().Add("Location", "captcha")
  26. rw.WriteHeader(http.StatusSeeOther)
  27. }
  28. func showCaptcha(rw http.ResponseWriter, req *http.Request) {
  29. session, err := store.Get(req, sessionName)
  30. if err != nil {
  31. log.Printf("Unable to get session: %s", err.Error())
  32. rw.Header().Add("Location", "failure")
  33. rw.WriteHeader(http.StatusSeeOther)
  34. return
  35. }
  36. captchaId, ok := session.Values[captchaKey]
  37. if !ok || !captcha.Reload(captchaId.(string)) {
  38. captchaId = captcha.New()
  39. session.Values[captchaKey] = captchaId
  40. if err := session.Save(req, rw); err != nil {
  41. log.Printf("Unable to save session: %s", err.Error())
  42. rw.Header().Add("Location", "failure")
  43. rw.WriteHeader(http.StatusSeeOther)
  44. return
  45. }
  46. }
  47. _ = captchaTemplate.ExecuteTemplate(rw, "captcha.html", map[string]interface{}{
  48. csrf.TemplateTag: csrf.TemplateField(req),
  49. })
  50. }
  51. func writeCaptchaImage(rw http.ResponseWriter, req *http.Request) {
  52. captchaId, ok := findCaptcha(req)
  53. if !ok {
  54. rw.WriteHeader(http.StatusForbidden)
  55. return
  56. }
  57. rw.Header().Set("Cache-Control", "no-cache")
  58. rw.Header().Set("Content-Type", "image/png")
  59. if err := captcha.WriteImage(rw, captchaId, captcha.StdWidth, captcha.StdHeight); err != nil {
  60. log.Printf("Unable to generate image captcha: %s", err.Error())
  61. rw.WriteHeader(http.StatusInternalServerError)
  62. return
  63. }
  64. }
  65. func writeCaptchaAudio(rw http.ResponseWriter, req *http.Request) {
  66. captchaId, ok := findCaptcha(req)
  67. if !ok {
  68. rw.WriteHeader(http.StatusForbidden)
  69. return
  70. }
  71. rw.Header().Set("Cache-Control", "no-cache")
  72. rw.Header().Set("Content-Type", "audio/wav")
  73. rw.Header().Set("Content-Disposition", "attachment")
  74. if err := captcha.WriteAudio(rw, captchaId, "en"); err != nil {
  75. log.Printf("Unable to generate audio captcha: %s", err.Error())
  76. rw.WriteHeader(http.StatusInternalServerError)
  77. return
  78. }
  79. }
  80. func handleSolve(rw http.ResponseWriter, req *http.Request) {
  81. captchaId, ok := findCaptcha(req)
  82. if !ok {
  83. rw.WriteHeader(http.StatusForbidden)
  84. return
  85. }
  86. digits := req.Form.Get("captcha")
  87. if !captcha.VerifyString(captchaId, digits) {
  88. rw.Header().Add("Location", "failure")
  89. rw.WriteHeader(http.StatusSeeOther)
  90. return
  91. }
  92. session, err := store.Get(req, sessionName)
  93. if err != nil {
  94. log.Printf("Unable to get session: %s", err.Error())
  95. rw.Header().Add("Location", "failure")
  96. rw.WriteHeader(http.StatusSeeOther)
  97. return
  98. }
  99. if sendMail(session.Values[replyToKey].(string), session.Values[bodyKey].(string)) {
  100. rw.Header().Add("Location", "success")
  101. rw.WriteHeader(http.StatusSeeOther)
  102. } else {
  103. rw.Header().Add("Location", "failure")
  104. rw.WriteHeader(http.StatusSeeOther)
  105. }
  106. }
  107. func findCaptcha(req *http.Request) (string, bool) {
  108. session, err := store.Get(req, sessionName)
  109. if err != nil {
  110. log.Printf("Unable to get session: %s", err.Error())
  111. return "", false
  112. }
  113. captchaId, ok := session.Values[captchaKey]
  114. if !ok {
  115. return "", false
  116. }
  117. return captchaId.(string), true
  118. }