mirror of
https://github.com/librecaptcha/lc-core.git
synced 2025-04-20 10:37:20 -04:00
Merge pull request #3 from SanBlig/framework
Initial commit for the framework
This commit is contained in:
commit
f8a91db4ca
@ -16,3 +16,5 @@ lazy val root = (project in file(".")).
|
|||||||
libraryDependencies += "com.sksamuel.scrimage" %% "scrimage-filters" % "2.1.8"
|
libraryDependencies += "com.sksamuel.scrimage" %% "scrimage-filters" % "2.1.8"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fork in run := true
|
||||||
|
BIN
lib/h2-1.4.197.jar
Executable file
BIN
lib/h2-1.4.197.jar
Executable file
Binary file not shown.
@ -1,24 +0,0 @@
|
|||||||
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(10000).toString
|
|
||||||
val challenge = new Challenge(token, image)
|
|
||||||
val answer = "about"
|
|
||||||
tokenAnswer += token -> answer
|
|
||||||
challenge
|
|
||||||
}
|
|
||||||
def checkAnswer(token: String, input: String): Boolean = {
|
|
||||||
tokenAnswer(token) == input
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
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)
|
|
@ -1,43 +0,0 @@
|
|||||||
import com.sksamuel.scrimage._
|
|
||||||
import java.io._
|
|
||||||
|
|
||||||
class CaptchaLibrary {
|
|
||||||
val captchas = List(new BlurCaptcha, new LabelCaptcha, new FilterCaptcha)
|
|
||||||
var tokenCaptcha = scala.collection.mutable.Map[String, CaptchaProvider]()
|
|
||||||
def init = {}
|
|
||||||
def shutdown = {}
|
|
||||||
def getChallenge(): Challenge = {
|
|
||||||
//choose a captcha provider randomly
|
|
||||||
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 = {
|
|
||||||
val result = tokenCaptcha(token).checkAnswer(token, input)
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trait CaptchaProvider {
|
|
||||||
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)
|
|
||||||
|
|
||||||
object LibreCaptcha {
|
|
||||||
def main(args: Array[String]) {
|
|
||||||
val captcha = new CaptchaLibrary
|
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +1,34 @@
|
|||||||
|
package lc
|
||||||
|
|
||||||
import com.sksamuel.scrimage._
|
import com.sksamuel.scrimage._
|
||||||
import com.sksamuel.scrimage.filter._
|
import com.sksamuel.scrimage.filter._
|
||||||
import java.awt.image.BufferedImage
|
import java.awt.image.BufferedImage
|
||||||
import java.awt.{Graphics2D,Color,Font}
|
import java.awt.Font
|
||||||
|
import java.awt.Color
|
||||||
|
|
||||||
class FilterCaptcha extends CaptchaProvider {
|
class FilterChallenge extends ChallengeProvider {
|
||||||
val tokenAnswer = scala.collection.mutable.Map[String, String]()
|
val id = "filter"
|
||||||
def getChallenge(): Challenge = {
|
def returnChallenge(): (Image, String) = {
|
||||||
val filterTypes = List(new FilterType1, new FilterType2)
|
val filterTypes = List(new FilterType1, new FilterType2)
|
||||||
val r = new scala.util.Random
|
val r = new scala.util.Random
|
||||||
val alphabet = "abcdefghijklmnopqrstuvwxyz"
|
val alphabet = "abcdefghijklmnopqrstuvwxyz"
|
||||||
val n = 8
|
val n = 8
|
||||||
val answer = Stream.continually(r.nextInt(alphabet.size)).map(alphabet).take(n).mkString
|
val secret = Stream.continually(r.nextInt(alphabet.size)).map(alphabet).take(n).mkString
|
||||||
val token = scala.util.Random.nextInt(10000).toString
|
|
||||||
synchronized {
|
|
||||||
tokenAnswer += token -> answer
|
|
||||||
}
|
|
||||||
val canvas = new BufferedImage(225, 50, BufferedImage.TYPE_INT_RGB)
|
val canvas = new BufferedImage(225, 50, BufferedImage.TYPE_INT_RGB)
|
||||||
val g = canvas.createGraphics()
|
val g = canvas.createGraphics()
|
||||||
g.setColor(Color.WHITE)
|
g.setColor(Color.WHITE)
|
||||||
g.fillRect(0, 0, canvas.getWidth, canvas.getHeight)
|
g.fillRect(0, 0, canvas.getWidth, canvas.getHeight)
|
||||||
g.setColor(Color.BLACK)
|
g.setColor(Color.BLACK)
|
||||||
g.setFont(new Font("Serif", Font.PLAIN, 30))
|
g.setFont(new Font("Serif", Font.PLAIN, 30))
|
||||||
g.drawString(answer, 5, 30)
|
g.drawString(secret, 5, 30)
|
||||||
g.dispose()
|
g.dispose()
|
||||||
var image = new Image(canvas, ImageMetadata.empty)
|
var image = new Image(canvas, ImageMetadata.empty)
|
||||||
val s = scala.util.Random.nextInt(2)
|
val s = scala.util.Random.nextInt(2)
|
||||||
image = filterTypes(s).applyFilter(image)
|
image = filterTypes(s).applyFilter(image)
|
||||||
val challenge = new Challenge(token, image)
|
(image, secret)
|
||||||
challenge
|
|
||||||
}
|
}
|
||||||
def checkAnswer(token: String, input: String): Boolean = {
|
def checkAnswer(secret: String, answer: String): Boolean = {
|
||||||
tokenAnswer(token) == input
|
secret == answer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,3 +59,4 @@ class FilterType2 extends FilterType {
|
|||||||
image
|
image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
76
src/main/scala/lc/Main.scala
Normal file
76
src/main/scala/lc/Main.scala
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package lc
|
||||||
|
|
||||||
|
import com.sksamuel.scrimage._
|
||||||
|
import java.sql._
|
||||||
|
import java.io._
|
||||||
|
|
||||||
|
trait ChallengeProvider {
|
||||||
|
val id: String
|
||||||
|
def returnChallenge(): (Image, String)
|
||||||
|
def checkAnswer(secret: String, answer: String): Boolean
|
||||||
|
//TODO: def configure(): Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
class Captcha {
|
||||||
|
val con: Connection = DriverManager.getConnection("jdbc:h2:./captcha", "sa", "")
|
||||||
|
val stmt: Statement = con.createStatement()
|
||||||
|
stmt.execute("CREATE TABLE IF NOT EXISTS challenge(token varchar, id varchar, secret varchar, image blob)")
|
||||||
|
val insertPstmt: PreparedStatement = con.prepareStatement("INSERT INTO challenge(token, id, secret) VALUES (?, ?, ?)")
|
||||||
|
val selectPstmt: PreparedStatement = con.prepareStatement("SELECT secret FROM challenge WHERE token = ?")
|
||||||
|
|
||||||
|
def getCaptcha(): Boolean = {
|
||||||
|
val provider = new FilterChallenge
|
||||||
|
val (token, image) = this.getChallenge(provider)
|
||||||
|
image.output(new File("Captcha.png"))
|
||||||
|
println(s"Token: ${token}")
|
||||||
|
println("Enter your answer: ")
|
||||||
|
val answer = scala.io.StdIn.readLine()
|
||||||
|
this.getAnswer(token, answer, provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
def getChallenge(provider: ChallengeProvider): (String, Image) = {
|
||||||
|
val (image, secret) = provider.returnChallenge()
|
||||||
|
val token = scala.util.Random.nextInt(10000).toString
|
||||||
|
insertPstmt.setString(1, token)
|
||||||
|
insertPstmt.setString(2, provider.id)
|
||||||
|
insertPstmt.setString(3, secret)
|
||||||
|
//TODO: insert image into database
|
||||||
|
insertPstmt.executeUpdate()
|
||||||
|
(token, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
def getAnswer(token: String, answer: String, provider: ChallengeProvider): Boolean = {
|
||||||
|
selectPstmt.setString(1, token)
|
||||||
|
val rs: ResultSet = selectPstmt.executeQuery()
|
||||||
|
rs.next()
|
||||||
|
val secret = rs.getString("secret")
|
||||||
|
provider.checkAnswer(secret, answer)
|
||||||
|
}
|
||||||
|
|
||||||
|
def display(): Unit = {
|
||||||
|
val rs: ResultSet = stmt.executeQuery("SELECT * FROM challenge")
|
||||||
|
println("token\t\tid\t\tsecret\t\timage")
|
||||||
|
while(rs.next()) {
|
||||||
|
val token = rs.getString("token")
|
||||||
|
val id = rs.getString("id")
|
||||||
|
val secret = rs.getString("secret")
|
||||||
|
val image = rs.getString("image")
|
||||||
|
println(s"${token}\t\t${id}\t\t${secret}\t\t${image}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def closeConnection(): Unit = {
|
||||||
|
con.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object LCFramework{
|
||||||
|
def main(args: scala.Array[String]) {
|
||||||
|
val captcha = new Captcha
|
||||||
|
val result = captcha.getCaptcha()
|
||||||
|
println(result)
|
||||||
|
captcha.display()
|
||||||
|
captcha.closeConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user