1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-02 10:56:25 -07:00
gochan/pkg/posting/captcha.go

121 lines
3.8 KiB
Go

package posting
import (
"fmt"
"image/color"
"net/http"
"strconv"
"github.com/gochan-org/gochan/pkg/building"
"github.com/gochan-org/gochan/pkg/config"
"github.com/gochan-org/gochan/pkg/gclog"
"github.com/gochan-org/gochan/pkg/gcsql"
"github.com/gochan-org/gochan/pkg/gctemplates"
"github.com/gochan-org/gochan/pkg/gcutil"
"github.com/gochan-org/gochan/pkg/serverutil"
"github.com/mojocn/base64Captcha"
)
var (
captchaString *base64Captcha.DriverString
driver *base64Captcha.DriverString
)
type captchaJSON struct {
CaptchaID string `json:"id"`
Base64String string `json:"image"`
Result string `json:"-"`
TempPostIndex string `json:"-"`
EmailCmd string `json:"-"`
}
// InitCaptcha prepares the captcha driver for use
func InitCaptcha() {
boardConfig := config.GetBoardConfig("")
if !boardConfig.UseCaptcha {
return
}
driver = base64Captcha.NewDriverString(
boardConfig.CaptchaHeight, boardConfig.CaptchaWidth, 0, 0, 6,
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
&color.RGBA{0, 0, 0, 0}, nil).ConvertFonts()
}
// ServeCaptcha handles requests to /captcha if UseCaptcha is enabled in gochan.json
func ServeCaptcha(writer http.ResponseWriter, request *http.Request) {
boardConfig := config.GetBoardConfig("")
if !boardConfig.UseCaptcha {
return
}
var err error
if err = request.ParseForm(); err != nil {
serverutil.ServeErrorPage(writer, gclog.Print(gclog.LErrorLog, "Error parsing request form: ", err.Error()))
return
}
tempPostIndexStr := request.FormValue("temppostindex")
var tempPostIndex int
if tempPostIndex, err = strconv.Atoi(tempPostIndexStr); err != nil {
tempPostIndexStr = "-1"
tempPostIndex = 0
}
emailCommand := request.FormValue("emailcmd")
id, b64 := getCaptchaImage()
captchaStruct := captchaJSON{id, b64, "", tempPostIndexStr, emailCommand}
useJSON := request.FormValue("json") == "1"
if useJSON {
writer.Header().Add("Content-Type", "application/json")
str, _ := gcutil.MarshalJSON(captchaStruct, false)
serverutil.MinifyWriter(writer, []byte(str), "application/json")
return
}
if request.FormValue("reload") == "Reload" {
request.Form.Del("reload")
request.Form.Add("didreload", "1")
ServeCaptcha(writer, request)
return
}
writer.Header().Add("Content-Type", "text/html")
captchaID := request.FormValue("captchaid")
captchaAnswer := request.FormValue("captchaanswer")
if captchaID != "" && request.FormValue("didreload") != "1" {
goodAnswer := base64Captcha.DefaultMemStore.Verify(captchaID, captchaAnswer, true)
if goodAnswer {
if tempPostIndex > -1 && tempPostIndex < len(gcsql.TempPosts) {
// came from a /post redirect, insert the specified temporary post
// and redirect to the thread
gcsql.InsertPost(&gcsql.TempPosts[tempPostIndex], emailCommand == "noko")
building.BuildBoards(false, gcsql.TempPosts[tempPostIndex].BoardID)
building.BuildFrontPage()
url := gcsql.TempPosts[tempPostIndex].GetURL(false)
// move the end Post to the current index and remove the old end Post. We don't
// really care about order as long as tempPost validation doesn't get jumbled up
gcsql.TempPosts[tempPostIndex] = gcsql.TempPosts[len(gcsql.TempPosts)-1]
gcsql.TempPosts = gcsql.TempPosts[:len(gcsql.TempPosts)-1]
http.Redirect(writer, request, url, http.StatusFound)
return
}
} else {
captchaStruct.Result = "Incorrect CAPTCHA"
}
}
if err = serverutil.MinifyTemplate(gctemplates.Captcha, captchaStruct, writer, "text/html"); err != nil {
fmt.Fprintf(writer,
gclog.Print(gclog.LErrorLog, "Error executing captcha template: ", err.Error()))
}
}
func getCaptchaImage() (captchaID, chaptchaB64 string) {
boardConfig := config.GetBoardConfig("")
if !boardConfig.UseCaptcha {
return
}
captcha := base64Captcha.NewCaptcha(driver, base64Captcha.DefaultMemStore)
captchaID, chaptchaB64, _ = captcha.Generate()
return
}