diff --git a/src/main/scala/BlurCaptcha.scala b/src/main/scala/BlurCaptcha.scala new file mode 100644 index 0000000..aabd9af --- /dev/null +++ b/src/main/scala/BlurCaptcha.scala @@ -0,0 +1,31 @@ +import com.sksamuel.scrimage._ +import com.sksamuel.scrimage.filter.GaussianBlurFilter +import java.io._ + +class BlurCaptcha extends CaptchaProvider { + val tokenAnswer = scala.collection.mutable.Map[String, String]() + val imageFiles = new File("known").listFiles.toList + def getChallenge(): (Challenge) = { + val r = scala.util.Random.nextInt(imageFiles.length) + val chosenImage = imageFiles(r) + var image = Image.fromStream(new FileInputStream(chosenImage)) + val blur = new GaussianBlurFilter(5) + blur.apply(image) + val s = scala.util.Random + val token = s.nextInt(1000).toString + val challenge = new Challenge(token, image) + val answer = "about" + tokenAnswer += token -> answer + challenge + } + def checkAnswer(token: String, input: String): Boolean = { + if(tokenAnswer(token)==input) + { + true + } + else + { + false + } + } +} diff --git a/src/main/scala/LabelCaptcha.scala b/src/main/scala/LabelCaptcha.scala new file mode 100644 index 0000000..40bfaad --- /dev/null +++ b/src/main/scala/LabelCaptcha.scala @@ -0,0 +1,73 @@ +import java.io.File +import javax.imageio.ImageIO +import scala.collection.mutable.Map +import java.nio.file.{Files,Path,StandardCopyOption} +import java.awt.image.BufferedImage +import java.awt.{Graphics2D,Color} + +class LabelCaptcha extends CaptchaProvider { + var knownFiles = new File("known").list.toList + var unknownFiles = new File("unknown").list.toList + val tokenImagePair = Map[String, ImagePair]() + val unknownAnswers = Map[String, Map[String, Int]]() + val total = Map[String, Int]() + for(file <- unknownFiles) { + unknownAnswers += file -> Map[String, Int]() + total += file -> 0 + } + def getChallenge(): Challenge = synchronized { + val r = scala.util.Random.nextInt(knownFiles.length) + val s = scala.util.Random.nextInt(unknownFiles.length) + val knownImageFile = knownFiles(r) + val unknownImageFile = unknownFiles(s) + val ip = new ImagePair(knownImageFile, unknownImageFile) + val token = scala.util.Random.nextInt(10000).toString + tokenImagePair += token -> ip + var knownImage = ImageIO.read(new File("known/"+knownImageFile)) + var unknownImage = ImageIO.read(new File("unknown/"+unknownImageFile)) + val width = knownImage.getWidth()+unknownImage.getWidth() + val height = List(knownImage.getHeight(), unknownImage.getHeight()).max + val imageType = knownImage.getType() + val finalImage = new BufferedImage(width, height, imageType) + val g = finalImage.createGraphics() + g.setColor(Color.WHITE) + g.fillRect(0, 0, finalImage.getWidth(), finalImage.getHeight()) + g.drawImage(knownImage, null, 0, 0) + g.drawImage(unknownImage, null, knownImage.getWidth(), 0) + g.dispose() + val challenge = new Challenge(token, finalImage) + challenge + } + def checkAnswer(token: String, input: String): Boolean = synchronized { + val expectedAnswer = tokenImagePair(token).known.split('.')(0) + val userAnswer = input.split(' ') + if(userAnswer(0)==expectedAnswer) { + val unknownFile = tokenImagePair(token).unknown + if((unknownAnswers(unknownFile)).contains(userAnswer(1))) + { + unknownAnswers(unknownFile)(userAnswer(1)) += 1 + total(unknownFile) += 1 + } + else + { + unknownAnswers(unknownFile)+=(userAnswer(1)) -> 1 + total(unknownFile) += 1 + } + if(total(unknownFile)>=3) { + if((unknownAnswers(unknownFile)(userAnswer(1))/total(unknownFile))>=0.9) + { + unknownAnswers -= unknownFile + Files.move(new File("unknown/"+unknownFile).toPath, new File("known/"+userAnswer(1)+".png").toPath, StandardCopyOption.REPLACE_EXISTING) + knownFiles = new File("known").list.toList + unknownFiles = new File("unknown").list.toList + } + } + true + } + else { + false + } + } +} + +class ImagePair(val known: String, val unknown: String) diff --git a/src/main/scala/Main.scala b/src/main/scala/Main.scala index 6b2080e..cd99b56 100644 --- a/src/main/scala/Main.scala +++ b/src/main/scala/Main.scala @@ -2,45 +2,46 @@ import com.sksamuel.scrimage._ import java.io._ class CaptchaLibrary { - var tokenAnswer = scala.collection.mutable.Map[String, String]() + val captchas = List(new BlurCaptcha, new LabelCaptcha) + var tokenCaptcha = scala.collection.mutable.Map[String, CaptchaProvider]() def init = {} def shutdown = {} def getChallenge(): Challenge = { //choose a captcha provider randomly - val blurCaptcha = new BlurCaptcha - val (challenge, answer) = blurCaptcha.getChallenge() - tokenAnswer += challenge.token->answer + val r = scala.util.Random.nextInt(2) + val captchaInstance = captchas(r) + val challenge = captchaInstance.getChallenge() + tokenCaptcha += challenge.token -> captchaInstance challenge } def checkAnswer(token: String, input: String): Boolean = { - if (tokenAnswer(token) == input) { - true - } - else { - false - } + val result = tokenCaptcha(token).checkAnswer(token, input) + result } } trait CaptchaProvider { - def getChallenge(): (Challenge, String) + def getChallenge(): (Challenge) + def checkAnswer(token: String, input: String): Boolean } class Challenge(val token: String, val image: Image) class Answer(val token: String, val input: String) -class BlurCaptcha extends CaptchaProvider { - def getChallenge(): (Challenge, String) = { - val inFileName = "image2.png" - var image = Image.fromStream(new FileInputStream(inFileName)) - image = image.filter(com.sksamuel.scrimage.filter.BlurFilter) - image.output(new File("blur.png")) - - val r = scala.util.Random - val token = r.nextInt(1000).toString - val challenge = new Challenge(token, image) - val answer = "about" - (challenge, answer) +object LibreCaptcha { + def main(args: Array[String]) { + val captcha = new CaptchaLibrary + var a = 0 + for (a <- 1 to 3) + { + val challenge = captcha.getChallenge() + println(s"Token: ${challenge.token}") + challenge.image.output(new File("Captcha.png")) + println("Enter your answer: ") + val input = scala.io.StdIn.readLine() + val result = captcha.checkAnswer(challenge.token, input) + println(s"Result: $result") + } } }