arnaucube
arnaucube/goCaptchaPublic Self-hosted repository
implemented: generate captcha and captcha solution, returns only captcha which has only fake image names and captchaid, stores also translator fake image name to real. Implemented read images dataset, storing in categories (folders names). GetImage reads fake image name, and translates to real image name, and serves the image content as fake image name
arnaucode idoctnef@openmailbox.org
Tue, 08 Aug 2017 21:23:28 +0200
commit

22d77500bdaceac099ae9b023feeb684f803c6e4

parent

ab69ef235d551f483ffe69cd08a29b68686a14ad

7 files changed, 189 insertions(+), 5 deletions(-)

jump to
A captcha.go

@@ -0,0 +1,67 @@

+package main + +import ( + "math/rand" + "os/exec" + "strings" +) + +type Captcha struct { + Id string `json:"id"` + Imgs []string `json:"imgs"` + Question string `json:"question"` + Date string `json:"date"` +} +type CaptchaSolution struct { + Id string `json:"id"` + Imgs []string `json:"imgs"` + ImgsSolution []string `json:"imgssolution"` + Question string `json:"question"` + Date string `json:"date"` +} +type ImgFakePath struct { + CaptchaId string `json:"captchaid"` + Real string `json:"real"` + Fake string `json:"fake"` +} + +func generateUUID() string { + out, err := exec.Command("uuidgen").Output() + check(err) + uuid := string(out) + uuid = strings.Replace(uuid, "\n", "", -1) + return uuid +} +func generateRandInt(min int, max int) int { + //rand.Seed(time.Now().UTC().UnixNano()) + return rand.Intn(max-min) + min +} +func generateCaptcha(count int) Captcha { + var captcha Captcha + var captchaSol CaptchaSolution + + captcha.Id = generateUUID() + captchaSol.Id = captcha.Id + + for i := 0; i < count; i++ { + nCateg := generateRandInt(0, len(categDataset)) + nImg := generateRandInt(0, len(dataset[categDataset[nCateg]])) + //imgFakePath + var imgFakePath ImgFakePath + imgFakePath.CaptchaId = captcha.Id + imgFakePath.Real = categDataset[nCateg] + "/" + dataset[categDataset[nCateg]][nImg] + imgFakePath.Fake = generateUUID() + ".png" + err := imgFakePathCollection.Insert(imgFakePath) + check(err) + captcha.Imgs = append(captcha.Imgs, imgFakePath.Fake) + captchaSol.Imgs = append(captchaSol.Imgs, dataset[categDataset[nCateg]][nImg]) + captchaSol.ImgsSolution = append(captchaSol.ImgsSolution, categDataset[nCateg]) + } + captcha.Question = "Select all leopards" + captchaSol.Question = "Select all leopards" + err := captchaCollection.Insert(captcha) + check(err) + err = captchaSolutionCollection.Insert(captchaSol) + check(err) + return captcha +}
M imageOperations.go → imageOperations.go

@@ -2,14 +2,27 @@ package main

import ( "bytes" + "fmt" "image" + "image/jpeg" "image/png" ) -func dataToPNG(data []byte, imageName string) (image.Image, error) { +func dataToImage(data []byte, imageExtension string) (image.Image, error) { reader := bytes.NewReader(data) - img, err := png.Decode(reader) + //img, err := png.Decode(reader) + var img image.Image + var err error + switch imageExtension { + case "png": + img, err = png.Decode(reader) + case "jpg", "jpeg": + img, err = jpeg.Decode(reader) + default: + img = nil + } if err != nil { + fmt.Println(err) return img, err } return img, err
M main.go → main.go

@@ -2,7 +2,10 @@ package main

import ( "log" + "math/rand" "net/http" + "strconv" + "time" "github.com/gorilla/handlers" )

@@ -10,10 +13,24 @@

func main() { savelog() log.Println("goCaptcha started") + rand.Seed(time.Now().UTC().UnixNano()) + + //connect with mongodb + readMongodbConfig("./mongodbConfig.json") + session, err := getSession() + check(err) + captchaCollection = getCollection(session, "captchas") + captchaSolutionCollection = getCollection(session, "captchassolutions") + imgFakePathCollection = getCollection(session, "imgfakepath") //start the server //http server start readServerConfig("./serverConfig.json") + + //read the filenames of the dataset + readDataset(serverConfig.ImgsFolder) + log.Println("dataset read") + log.Println("num of dataset categories: " + strconv.Itoa(len(dataset))) log.Println("server running") log.Print("port: ")
A mongoConfig.go

@@ -0,0 +1,51 @@

+package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + + mgo "gopkg.in/mgo.v2" +) + +//MongoConfig stores the configuration of mongodb to connect +type MongoConfig struct { + Ip string `json:"ip"` + Database string `json:"database"` +} + +var mongoConfig MongoConfig + +var captchaCollection *mgo.Collection +var captchaSolutionCollection *mgo.Collection +var imgFakePathCollection *mgo.Collection + +func readMongodbConfig(path string) { + file, e := ioutil.ReadFile(path) + if e != nil { + fmt.Println("error:", e) + } + content := string(file) + json.Unmarshal([]byte(content), &mongoConfig) +} + +func getSession() (*mgo.Session, error) { + session, err := mgo.Dial("mongodb://" + mongoConfig.Ip) + if err != nil { + panic(err) + } + //defer session.Close() + + // Optional. Switch the session to a monotonic behavior. + session.SetMode(mgo.Monotonic, true) + + // Optional. Switch the session to a monotonic behavior. + session.SetMode(mgo.Monotonic, true) + + return session, err +} +func getCollection(session *mgo.Session, collection string) *mgo.Collection { + + c := session.DB(mongoConfig.Database).C(collection) + return c +}
A mongodbConfig.json

@@ -0,0 +1,4 @@

+{ + "ip": "127.0.0.1", + "database": "goCaptcha" +}
A readDataset.go

@@ -0,0 +1,21 @@

+package main + +import ( + "io/ioutil" +) + +var dataset map[string][]string +var categDataset []string + +func readDataset(path string) { + dataset = make(map[string][]string) + + folders, _ := ioutil.ReadDir(path) + for _, folder := range folders { + categDataset = append(categDataset, folder.Name()) + folderFiles, _ := ioutil.ReadDir(path + "/" + folder.Name()) + for _, file := range folderFiles { + dataset[folder.Name()] = append(dataset[folder.Name()], file.Name()) + } + } +}
M serverRoutes.go → serverRoutes.go

@@ -6,6 +6,9 @@ "fmt"

"image/jpeg" "io/ioutil" "net/http" + "strings" + + "gopkg.in/mgo.v2/bson" "github.com/gorilla/mux" )

@@ -43,12 +46,20 @@ func GetImage(w http.ResponseWriter, r *http.Request) {

vars := mux.Vars(r) imageName := vars["imageName"] - file, err := ioutil.ReadFile(serverConfig.ImgsFolder + "/" + imageName) + imgFakePath := ImgFakePath{} + err := imgFakePathCollection.Find(bson.M{"fake": imageName}).One(&imgFakePath) + check(err) + + fmt.Println(serverConfig.ImgsFolder + "/" + imgFakePath.Real) + + file, err := ioutil.ReadFile(serverConfig.ImgsFolder + "/" + imgFakePath.Real) if err != nil { fmt.Fprintln(w, err) } - img, err := dataToPNG(file, imageName) + pathSplited := strings.Split(imgFakePath.Real, ".") + imageExtension := pathSplited[len(pathSplited)-1] + img, err := dataToImage(file, imageExtension) if err != nil { fmt.Fprintln(w, "image "+imageName+" does not exist in server")

@@ -58,7 +69,7 @@ }

} func GetCaptcha(w http.ResponseWriter, r *http.Request) { - resp := "" + resp := generateCaptcha(6) jsonResp, err := json.Marshal(resp) check(err) fmt.Fprintln(w, string(jsonResp))