arnaucube
arnaucube/goCaptchaPublic Self-hosted repository
goCaptcha/captcha.go
captcha.goRaw
  1package main
  2
  3import (
  4	"math/rand"
  5	"os/exec"
  6	"strings"
  7	"time"
  8
  9	"gopkg.in/mgo.v2/bson"
 10)
 11
 12type Captcha struct {
 13	Id       string   `json:"id"`
 14	Imgs     []string `json:"imgs"`
 15	Question string   `json:"question"`
 16	Date     string   `json:"date"`
 17}
 18type CaptchaSol struct {
 19	Id           string   `json:"id"`
 20	ImgsSolution []string `json:"imgssolution"`
 21	Question     string   `json:"question"` //select all X
 22	Date         int64    `json:"date"`
 23	IP           string   `json:"ip"`
 24}
 25type CaptchaAnswer struct {
 26	CaptchaId string `json:"captchaid"`
 27	Selection []int  `json:"selection"`
 28}
 29type ImgFakePath struct {
 30	CaptchaId string `json:"captchaid"`
 31	Real      string `json:"real"`
 32	Fake      string `json:"fake"`
 33}
 34type SuspiciousIP struct {
 35	Date  int64  `json:"date"`
 36	IP    string `json:"ip"`
 37	Count int    `json:"count"`
 38}
 39
 40func generateUUID() string {
 41	out, err := exec.Command("uuidgen").Output()
 42	check(err)
 43	uuid := string(out)
 44	uuid = strings.Replace(uuid, "\n", "", -1)
 45	return uuid
 46}
 47func generateRandInt(min int, max int) int {
 48	//rand.Seed(time.Now().UTC().UnixNano())
 49	return rand.Intn(max-min) + min
 50}
 51func generateQuestionFromCategoriesArray(imgs []string) string {
 52	n := generateRandInt(0, len(imgs))
 53	return imgs[n]
 54}
 55func generateCaptcha(count int, ip string) Captcha {
 56	var captcha Captcha
 57	var captchaSol CaptchaSol
 58
 59	captcha.Id = generateUUID()
 60	captchaSol.Id = captcha.Id
 61
 62	for i := 0; i < count; i++ {
 63		nCateg := generateRandInt(0, len(categDataset))
 64		nImg := generateRandInt(0, len(dataset[categDataset[nCateg]]))
 65		//imgFakePath
 66		var imgFakePath ImgFakePath
 67		imgFakePath.CaptchaId = captcha.Id
 68		imgFakePath.Real = categDataset[nCateg] + "/" + dataset[categDataset[nCateg]][nImg]
 69		imgFakePath.Fake = generateUUID() + ".png"
 70		err := imgFakePathCollection.Insert(imgFakePath)
 71		check(err)
 72		captcha.Imgs = append(captcha.Imgs, imgFakePath.Fake)
 73		captchaSol.ImgsSolution = append(captchaSol.ImgsSolution, categDataset[nCateg])
 74	}
 75	question := generateQuestionFromCategoriesArray(captchaSol.ImgsSolution)
 76	captcha.Question = question
 77	captchaSol.Question = question
 78	captchaSol.Date = time.Now().Unix()
 79	captchaSol.IP = ip
 80	err := captchaSolCollection.Insert(captchaSol)
 81	check(err)
 82	return captcha
 83}
 84func validateCaptcha(captchaAnswer CaptchaAnswer, ip string) bool {
 85	var solved bool
 86	solved = true
 87	captchaSol := CaptchaSol{}
 88	err := captchaSolCollection.Find(bson.M{"id": captchaAnswer.CaptchaId}).One(&captchaSol)
 89	check(err)
 90	for k, imgSol := range captchaSol.ImgsSolution {
 91		if imgSol == captchaSol.Question {
 92			if captchaAnswer.Selection[k] == 1 {
 93				//correct
 94			} else {
 95				solved = false
 96			}
 97		}
 98		if imgSol != captchaSol.Question {
 99			if captchaAnswer.Selection[k] == 0 {
100				//correct
101			} else {
102				solved = false
103			}
104		}
105	}
106
107	//time elapsed from captcha generation comprovation
108	date := time.Unix(captchaSol.Date, 0)
109	elapsed := time.Since(date)
110	if elapsed.Seconds() < 1 {
111		solved = false
112	}
113	if elapsed.Seconds() > 60 {
114		solved = false
115	}
116	//ip comprovation
117	if captchaSol.IP != ip {
118		solved = false
119	}
120	return solved
121}