diff --git a/captcha.go b/captcha.go new file mode 100644 index 0000000..3659b25 --- /dev/null +++ b/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 +} diff --git a/imageOperations.go b/imageOperations.go index 8af06b3..ea9a623 100644 --- a/imageOperations.go +++ b/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 diff --git a/main.go b/main.go index 98d85da..75a4970 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,10 @@ package main import ( "log" + "math/rand" "net/http" + "strconv" + "time" "github.com/gorilla/handlers" ) @@ -10,11 +13,25 @@ import ( 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: ") log.Println(serverConfig.ServerPort) diff --git a/mongoConfig.go b/mongoConfig.go new file mode 100644 index 0000000..bd02417 --- /dev/null +++ b/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 +} diff --git a/mongodbConfig.json b/mongodbConfig.json new file mode 100644 index 0000000..bd81350 --- /dev/null +++ b/mongodbConfig.json @@ -0,0 +1,4 @@ +{ + "ip": "127.0.0.1", + "database": "goCaptcha" +} diff --git a/readDataset.go b/readDataset.go new file mode 100644 index 0000000..c3bb50b --- /dev/null +++ b/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()) + } + } +} diff --git a/serverRoutes.go b/serverRoutes.go index a455080..01053bc 100644 --- a/serverRoutes.go +++ b/serverRoutes.go @@ -6,6 +6,9 @@ import ( "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 GetImage(w http.ResponseWriter, r *http.Request) { } func GetCaptcha(w http.ResponseWriter, r *http.Request) { - resp := "" + resp := generateCaptcha(6) jsonResp, err := json.Marshal(resp) check(err) fmt.Fprintln(w, string(jsonResp))