mirror of
https://github.com/librecaptcha/lc-core.git
synced 2025-02-06 00:38:06 -05:00
Separate captcha classes and add LabelCaptcha
LabelCaptcha creates a pair of known and unknown images. BlurCaptcha is modified to use a better filter.
This commit is contained in:
parent
4610245b38
commit
dfa146e139
31
src/main/scala/BlurCaptcha.scala
Normal file
31
src/main/scala/BlurCaptcha.scala
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
src/main/scala/LabelCaptcha.scala
Normal file
73
src/main/scala/LabelCaptcha.scala
Normal file
@ -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)
|
@ -2,45 +2,46 @@ import com.sksamuel.scrimage._
|
|||||||
import java.io._
|
import java.io._
|
||||||
|
|
||||||
class CaptchaLibrary {
|
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 init = {}
|
||||||
def shutdown = {}
|
def shutdown = {}
|
||||||
def getChallenge(): Challenge = {
|
def getChallenge(): Challenge = {
|
||||||
//choose a captcha provider randomly
|
//choose a captcha provider randomly
|
||||||
val blurCaptcha = new BlurCaptcha
|
val r = scala.util.Random.nextInt(2)
|
||||||
val (challenge, answer) = blurCaptcha.getChallenge()
|
val captchaInstance = captchas(r)
|
||||||
tokenAnswer += challenge.token->answer
|
val challenge = captchaInstance.getChallenge()
|
||||||
|
tokenCaptcha += challenge.token -> captchaInstance
|
||||||
challenge
|
challenge
|
||||||
}
|
}
|
||||||
def checkAnswer(token: String, input: String): Boolean = {
|
def checkAnswer(token: String, input: String): Boolean = {
|
||||||
if (tokenAnswer(token) == input) {
|
val result = tokenCaptcha(token).checkAnswer(token, input)
|
||||||
true
|
result
|
||||||
}
|
|
||||||
else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CaptchaProvider {
|
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 Challenge(val token: String, val image: Image)
|
||||||
|
|
||||||
class Answer(val token: String, val input: String)
|
class Answer(val token: String, val input: String)
|
||||||
|
|
||||||
class BlurCaptcha extends CaptchaProvider {
|
object LibreCaptcha {
|
||||||
def getChallenge(): (Challenge, String) = {
|
def main(args: Array[String]) {
|
||||||
val inFileName = "image2.png"
|
val captcha = new CaptchaLibrary
|
||||||
var image = Image.fromStream(new FileInputStream(inFileName))
|
var a = 0
|
||||||
image = image.filter(com.sksamuel.scrimage.filter.BlurFilter)
|
for (a <- 1 to 3)
|
||||||
image.output(new File("blur.png"))
|
{
|
||||||
|
val challenge = captcha.getChallenge()
|
||||||
val r = scala.util.Random
|
println(s"Token: ${challenge.token}")
|
||||||
val token = r.nextInt(1000).toString
|
challenge.image.output(new File("Captcha.png"))
|
||||||
val challenge = new Challenge(token, image)
|
println("Enter your answer: ")
|
||||||
val answer = "about"
|
val input = scala.io.StdIn.readLine()
|
||||||
(challenge, answer)
|
val result = captcha.checkAnswer(challenge.token, input)
|
||||||
|
println(s"Result: $result")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user