Refactor modules (#56)

* Refactor:Modules

Signed-off-by: Rahul Rudragoudar <rr83019@gmail.com>

* Add config file

Signed-off-by: Rahul Rudragoudar <rr83019@gmail.com>

* Restore sample images

Signed-off-by: Rahul Rudragoudar <rr83019@gmail.com>
This commit is contained in:
Rahul Rudragoudar 2021-02-24 15:21:16 +05:30 committed by GitHub
parent b66f777828
commit 6d04cdc3b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 328 additions and 242 deletions

3
.gitignore vendored
View File

@ -5,6 +5,9 @@
/project/** /project/**
/target/ /target/
**__pycache__ **__pycache__
.bloop
.metals
.vscode
# for various captcha # for various captcha
/known/ /known/

34
config.json Normal file
View File

@ -0,0 +1,34 @@
{
"randomSeed": 20,
"captchaExpiryTimeLimit": 5,
"captchas":{
"FilterChallenge":{
"name": "FilterChallenge",
"supportedLevels":["medium", "hard"],
"supportedMedia":["image"],
"supportedinputType":["text"],
"config":{}
},
"GifCaptcha":{
"name": "GifCaptcha",
"supportedLevels":["hard"],
"supportedMedia":["gif"],
"supportedinputType":["text"],
"config":{}
},
"ShadowTextCaptcha":{
"name": "ShadowTextCaptcha",
"supportedLevels":["easy"],
"supportedMedia":["image"],
"supportedinputType":["text"],
"config": {}
},
"RainDropsCaptcha":{
"name": "RainDropsCaptcha",
"supportedLevels":["easy","medium"],
"supportedMedia":["image"],
"supportedinputType":["text"],
"config":{}
}
}
}

View File

@ -1,4 +1,4 @@
package lc; package lc.captchas;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*; import java.awt.*;
@ -6,6 +6,9 @@ import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import lc.captchas.interfaces.Challenge;
import lc.captchas.interfaces.ChallengeProvider;
import lc.misc.HelperFunctions;
public class FontFunCaptcha implements ChallengeProvider{ public class FontFunCaptcha implements ChallengeProvider{

View File

@ -1,4 +1,4 @@
package lc; package lc.captchas;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics2D; import java.awt.Graphics2D;
@ -9,6 +9,10 @@ import java.io.IOException;
import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream; import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import lc.captchas.interfaces.Challenge;
import lc.captchas.interfaces.ChallengeProvider;
import lc.misc.HelperFunctions;
import lc.misc.GifSequenceWriter;
public class GifCaptcha implements ChallengeProvider{ public class GifCaptcha implements ChallengeProvider{

View File

@ -1,4 +1,4 @@
package lc; package lc.captchas;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.Graphics2D; import java.awt.Graphics2D;
@ -10,11 +10,14 @@ import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp; import java.awt.image.ConvolveOp;
import java.awt.image.Kernel; import java.awt.image.Kernel;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import lc.misc.HelperFunctions;
import lc.captchas.interfaces.Challenge;
import lc.captchas.interfaces.ChallengeProvider;
public class ShadowTextCaptcha implements ChallengeProvider{ public class ShadowTextCaptcha implements ChallengeProvider{
public String getId() { public String getId() {
return "ShadowText"; return "ShadowTextCaptcha";
} }
public boolean checkAnswer(String secret, String answer) { public boolean checkAnswer(String secret, String answer) {

View File

@ -1,4 +1,4 @@
package lc; package lc.captchas.interfaces;
public class Challenge { public class Challenge {
public final byte[] content; public final byte[] content;

View File

@ -1,6 +1,6 @@
package lc; package lc.captchas.interfaces;
interface ChallengeProvider { public interface ChallengeProvider {
public String getId(); public String getId();
public Challenge returnChallenge(); public Challenge returnChallenge();
public boolean checkAnswer(String secret, String answer); public boolean checkAnswer(String secret, String answer);

View File

@ -1,7 +1,7 @@
// This code was adapted from http://elliot.kroo.net/software/java/GifSequenceWriter/ // This code was adapted from http://elliot.kroo.net/software/java/GifSequenceWriter/
// It was available under CC By 3.0 // It was available under CC By 3.0
package lc; package lc.misc;
import javax.imageio.*; import javax.imageio.*;
import javax.imageio.metadata.*; import javax.imageio.metadata.*;
import javax.imageio.stream.*; import javax.imageio.stream.*;

View File

@ -1,4 +1,4 @@
package lc; package lc.misc;
import java.awt.*; import java.awt.*;

View File

@ -1,4 +1,4 @@
package lc;/* package lc.server;/*
* Copyright © 2005-2018 Amichai Rothman * Copyright © 2005-2018 Amichai Rothman
* *
* This file is part of JLHTTP - the Java Lightweight HTTP Server. * This file is part of JLHTTP - the Java Lightweight HTTP Server.

View File

@ -1,222 +1,20 @@
package lc package lc
import com.sksamuel.scrimage._ import org.json4s.DefaultFormats
import java.io.ByteArrayInputStream import org.json4s.jackson.JsonMethods._
import java.util.concurrent._ import scala.io.Source.fromFile
import java.util.UUID import lc.database.Statements
import java.sql.{Blob, ResultSet} import lc.core.{Captcha, CaptchaProviders}
import java.util.concurrent.atomic.AtomicInteger import lc.server.Server
import java.io._ import lc.background.BackgroundTask
import java.sql.Statement
case class Size(height: Int, width: Int)
case class Parameters(level: String, media: String, input_type: String, size: Option[Size])
case class Id(id: String)
case class Answer(answer: String, id: String)
case class ProviderSecret(provider: String, secret: String)
object CaptchaProviders {
val providers = Map(
"FilterChallenge" -> new FilterChallenge,
// "FontFunCaptcha" -> new FontFunCaptcha,
"GifCaptcha" -> new GifCaptcha,
"ShadowTextCaptcha" -> new ShadowTextCaptcha,
"RainDropsCaptcha" -> new RainDropsCP,
// "LabelCaptcha" -> new LabelCaptcha
)
def generateChallengeSamples() = {
providers.map {case (key, provider) =>
(key, provider.returnChallenge())
}
}
}
class Statements(dbConn: DBConn) {
val insertPstmt = dbConn.con.prepareStatement("INSERT INTO challenge(id, secret, provider, contentType, image) VALUES (?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS )
val mapPstmt = dbConn.con.prepareStatement("INSERT INTO mapId(uuid, token, lastServed) VALUES (?, ?, CURRENT_TIMESTAMP)")
val selectPstmt = dbConn.con.prepareStatement("SELECT c.secret, c.provider FROM challenge c, mapId m WHERE m.token=c.token AND DATEDIFF(MINUTE, CURRENT_TIMESTAMP, DATEADD(MINUTE, 1, m.lastServed)) > 0 AND m.uuid = ?")
val imagePstmt = dbConn.con.prepareStatement("SELECT image FROM challenge c, mapId m WHERE c.token=m.token AND m.uuid = ?")
val updateAttemptedPstmt = dbConn.con.prepareStatement("UPDATE challenge SET attempted = attempted+1 WHERE token = (SELECT m.token FROM mapId m, challenge c WHERE m.token=c.token AND m.uuid = ?)")
val tokenPstmt = dbConn.con.prepareStatement("SELECT token FROM challenge WHERE attempted < 10 ORDER BY RAND() LIMIT 1")
val deleteAnswerPstmt = dbConn.con.prepareStatement("DELETE FROM mapId WHERE uuid = ?")
val challengeGCPstmt = dbConn.con.prepareStatement("DELETE FROM challenge WHERE attempted >= 10 AND token NOT IN (SELECT token FROM mapId)")
val mapIdGCPstmt = dbConn.con.prepareStatement("DELETE FROM mapId WHERE DATEDIFF(MINUTE, CURRENT_TIMESTAMP, DATEADD(MINUTE, 1, lastServed)) < 0")
}
object Statements {
var dbConn: DBConn = _
val tlStmts = ThreadLocal.withInitial(() => new Statements(dbConn))
}
class Captcha(throttle: Int, dbConn: DBConn) {
import CaptchaProviders._
private val stmt = dbConn.getStatement()
stmt.execute("CREATE TABLE IF NOT EXISTS challenge(token int auto_increment, id varchar, secret varchar, provider varchar, contentType varchar, image blob, attempted int default 0, PRIMARY KEY(token))")
stmt.execute("CREATE TABLE IF NOT EXISTS mapId(uuid varchar, token int, lastServed timestamp, PRIMARY KEY(uuid), FOREIGN KEY(token) REFERENCES challenge(token) ON DELETE CASCADE)")
private val seed = System.currentTimeMillis.toString.substring(2,6).toInt
private val random = new scala.util.Random(seed)
def getNextRandomInt(max: Int) = random.synchronized {
random.nextInt(max)
}
def getProvider(): String = {
val keys = providers.keys
val providerIndex = keys.toVector(getNextRandomInt(keys.size))
providerIndex
}
def getCaptcha(id: Id): Array[Byte] = {
var image :Array[Byte] = null
var blob: Blob = null
try {
val imagePstmt = Statements.tlStmts.get.imagePstmt
imagePstmt.setString(1, id.id)
val rs: ResultSet = imagePstmt.executeQuery()
if(rs.next()){
blob = rs.getBlob("image")
if(blob != null){
image = blob.getBytes(1, blob.length().toInt)
}
}
image
} catch { case e: Exception =>
println(e)
image
}
}
private val uniqueIntCount = new AtomicInteger()
def generateChallenge(param: Parameters): Int = {
//TODO: eval params to choose a provider
val providerMap = getProvider()
val provider = providers(providerMap)
val challenge = provider.returnChallenge()
val blob = new ByteArrayInputStream(challenge.content)
val insertPstmt = Statements.tlStmts.get.insertPstmt
insertPstmt.setString(1, provider.getId)
insertPstmt.setString(2, challenge.secret)
insertPstmt.setString(3, providerMap)
insertPstmt.setString(4, challenge.contentType)
insertPstmt.setBlob(5, blob)
insertPstmt.executeUpdate()
val rs: ResultSet = insertPstmt.getGeneratedKeys()
val token = if(rs.next()){
rs.getInt("token")
}
println("Added new challenge: "+ token.toString)
token.asInstanceOf[Int]
}
val task = new Runnable {
def run(): Unit = {
try {
val mapIdGCPstmt = Statements.tlStmts.get.mapIdGCPstmt
mapIdGCPstmt.executeUpdate()
val challengeGCPstmt = Statements.tlStmts.get.challengeGCPstmt
challengeGCPstmt.executeUpdate()
val imageNum = stmt.executeQuery("SELECT COUNT(*) AS total FROM challenge")
var throttleIn = (throttle*1.1).toInt
if(imageNum.next())
throttleIn = (throttleIn-imageNum.getInt("total"))
while(0 < throttleIn){
generateChallenge(Parameters("","","",Option(Size(0,0))))
throttleIn -= 1
}
} catch { case e: Exception => println(e) }
}
}
def beginThread(delay: Int) : Unit = {
val ex = new ScheduledThreadPoolExecutor(1)
val thread = ex.scheduleWithFixedDelay(task, 1, delay, TimeUnit.SECONDS)
}
def getChallenge(param: Parameters): Id = {
try {
val tokenPstmt = Statements.tlStmts.get.tokenPstmt
val rs = tokenPstmt.executeQuery()
val tokenOpt = if(rs.next()) {
Some(rs.getInt("token"))
} else {
None
}
val updateAttemptedPstmt = Statements.tlStmts.get.updateAttemptedPstmt
val uuid = getUUID(tokenOpt.getOrElse(generateChallenge(param)))
updateAttemptedPstmt.setString(1, uuid)
updateAttemptedPstmt.executeUpdate()
Id(uuid)
} catch {case e: Exception =>
println(e)
Id(getUUID(-1))
}
}
def getUUID(id: Int): String = {
val uuid = UUID.randomUUID().toString
val mapPstmt = Statements.tlStmts.get.mapPstmt
mapPstmt.setString(1,uuid)
mapPstmt.setInt(2,id)
mapPstmt.executeUpdate()
uuid
}
def checkAnswer(answer: Answer): String = {
val selectPstmt = Statements.tlStmts.get.selectPstmt
selectPstmt.setString(1, answer.id)
val rs: ResultSet = selectPstmt.executeQuery()
val psOpt = if (rs.first()) {
val secret = rs.getString("secret")
val provider = rs.getString("provider")
val check = providers(provider).checkAnswer(secret, answer.answer)
val result = if(check) "TRUE" else "FALSE"
result
} else {
"EXPIRED"
}
val deleteAnswerPstmt = Statements.tlStmts.get.deleteAnswerPstmt
deleteAnswerPstmt.setString(1, answer.id)
deleteAnswerPstmt.executeUpdate()
psOpt
}
def display(): Unit = {
val rs: ResultSet = stmt.executeQuery("SELECT * FROM challenge")
println("token\t\tid\t\tsecret\t\tattempted")
while(rs.next()) {
val token = rs.getInt("token")
val id = rs.getString("id")
val secret = rs.getString("secret")
val attempted = rs.getString("attempted")
println(s"${token}\t\t${id}\t\t${secret}\t\t${attempted}\n\n")
}
val rss: ResultSet = stmt.executeQuery("SELECT * FROM mapId")
println("uuid\t\ttoken\t\tlastServed")
while(rss.next()){
val uuid = rss.getString("uuid")
val token = rss.getInt("token")
val lastServed = rss.getTimestamp("lastServed")
println(s"${uuid}\t\t${token}\t\t${lastServed}\n\n")
}
}
}
object LCFramework{ object LCFramework{
def main(args: scala.Array[String]) { def main(args: scala.Array[String]) {
val dbConn = new DBConn() val captcha = new Captcha()
Statements.dbConn = dbConn val server = new Server(8888, captcha)
val captcha = new Captcha(2, dbConn) val backgroudTask = new BackgroundTask(captcha, 10)
val server = new Server(8888, captcha, dbConn) backgroudTask.beginThread(2)
captcha.beginThread(2)
server.start() server.start()
} }
} }

View File

@ -0,0 +1,38 @@
package lc.background
import lc.database.Statements
import java.util.concurrent.{ScheduledThreadPoolExecutor, TimeUnit}
import lc.core.Captcha
import lc.core.{Parameters, Size}
class BackgroundTask(captcha: Captcha, throttle: Int) {
private val task = new Runnable {
def run(): Unit = {
try {
val mapIdGCPstmt = Statements.tlStmts.get.mapIdGCPstmt
mapIdGCPstmt.executeUpdate()
val challengeGCPstmt = Statements.tlStmts.get.challengeGCPstmt
challengeGCPstmt.executeUpdate()
val imageNum = Statements.tlStmts.get.getCountChallengeTable.executeQuery()
var throttleIn = (throttle*1.1).toInt
if(imageNum.next())
throttleIn = (throttleIn-imageNum.getInt("total"))
while(0 < throttleIn){
captcha.generateChallenge(Parameters("","","",Option(Size(0,0))))
throttleIn -= 1
}
} catch { case e: Exception => println(e) }
}
}
def beginThread(delay: Int) : Unit = {
val ex = new ScheduledThreadPoolExecutor(1)
val thread = ex.scheduleWithFixedDelay(task, 1, delay, TimeUnit.SECONDS)
}
}

View File

@ -1,10 +1,13 @@
package lc package lc.captchas
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.Font import java.awt.Font
import java.awt.Color import java.awt.Color
import lc.captchas.interfaces.ChallengeProvider
import lc.captchas.interfaces.Challenge
class FilterChallenge extends ChallengeProvider { class FilterChallenge extends ChallengeProvider {
def getId = "FilterChallenge" def getId = "FilterChallenge"

View File

@ -1,4 +1,4 @@
package lc package lc.captchas
import java.io.File import java.io.File
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
@ -7,6 +7,8 @@ import scala.collection.mutable.Map
import java.nio.file.{Files,Path,StandardCopyOption} import java.nio.file.{Files,Path,StandardCopyOption}
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import java.awt.{Graphics2D,Color} import java.awt.{Graphics2D,Color}
import lc.captchas.interfaces.ChallengeProvider
import lc.captchas.interfaces.Challenge
class LabelCaptcha extends ChallengeProvider { class LabelCaptcha extends ChallengeProvider {
private var knownFiles = new File("known").list.toList private var knownFiles = new File("known").list.toList

View File

@ -1,4 +1,4 @@
package lc package lc.captchas
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import java.awt.RenderingHints import java.awt.RenderingHints
@ -9,6 +9,9 @@ import java.io.ByteArrayOutputStream
import javax.imageio.ImageIO import javax.imageio.ImageIO
import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream; import javax.imageio.stream.MemoryCacheImageOutputStream;
import lc.captchas.interfaces.ChallengeProvider
import lc.captchas.interfaces.Challenge
import lc.misc.GifSequenceWriter
class Drop { class Drop {
var x = 0 var x = 0

View File

@ -0,0 +1,121 @@
package lc.core
import org.json4s.JsonAST.JValue
import java.sql.{Blob, ResultSet}
import java.util.UUID
import java.io.ByteArrayInputStream
import lc.database.Statements
import lc.core.CaptchaProviders
class Captcha {
def getCaptcha(id: Id): Array[Byte] = {
var image :Array[Byte] = null
var blob: Blob = null
try {
val imagePstmt = Statements.tlStmts.get.imagePstmt
imagePstmt.setString(1, id.id)
val rs: ResultSet = imagePstmt.executeQuery()
if(rs.next()){
blob = rs.getBlob("image")
if(blob != null){
image = blob.getBytes(1, blob.length().toInt)
}
}
image
} catch { case e: Exception =>
println(e)
image
}
}
def generateChallenge(param: Parameters): Int = {
//TODO: eval params to choose a provider
val provider = CaptchaProviders.getProvider()
val providerId = provider.getId()
val challenge = provider.returnChallenge()
val blob = new ByteArrayInputStream(challenge.content)
val insertPstmt = Statements.tlStmts.get.insertPstmt
insertPstmt.setString(1, provider.getId)
insertPstmt.setString(2, challenge.secret)
insertPstmt.setString(3, providerId)
insertPstmt.setString(4, challenge.contentType)
insertPstmt.setBlob(5, blob)
insertPstmt.executeUpdate()
val rs: ResultSet = insertPstmt.getGeneratedKeys()
val token = if(rs.next()){
rs.getInt("token")
}
println("Added new challenge: "+ token.toString)
token.asInstanceOf[Int]
}
def getChallenge(param: Parameters): Id = {
try {
val tokenPstmt = Statements.tlStmts.get.tokenPstmt
val rs = tokenPstmt.executeQuery()
val tokenOpt = if(rs.next()) {
Some(rs.getInt("token"))
} else {
None
}
val updateAttemptedPstmt = Statements.tlStmts.get.updateAttemptedPstmt
val uuid = getUUID(tokenOpt.getOrElse(generateChallenge(param)))
updateAttemptedPstmt.setString(1, uuid)
updateAttemptedPstmt.executeUpdate()
Id(uuid)
} catch {case e: Exception =>
println(e)
Id(getUUID(-1))
}
}
private def getUUID(id: Int): String = {
val uuid = UUID.randomUUID().toString
val mapPstmt = Statements.tlStmts.get.mapPstmt
mapPstmt.setString(1,uuid)
mapPstmt.setInt(2,id)
mapPstmt.executeUpdate()
uuid
}
def checkAnswer(answer: Answer): Result = {
val selectPstmt = Statements.tlStmts.get.selectPstmt
selectPstmt.setString(1, answer.id)
val rs: ResultSet = selectPstmt.executeQuery()
val psOpt = if (rs.first()) {
val secret = rs.getString("secret")
val provider = rs.getString("provider")
val check = CaptchaProviders.getProviderById(provider).checkAnswer(secret, answer.answer)
val result = if(check) "TRUE" else "FALSE"
result
} else {
"EXPIRED"
}
val deleteAnswerPstmt = Statements.tlStmts.get.deleteAnswerPstmt
deleteAnswerPstmt.setString(1, answer.id)
deleteAnswerPstmt.executeUpdate()
Result(psOpt)
}
def display(): Unit = {
val rs: ResultSet = Statements.tlStmts.get.getChallengeTable.executeQuery()
println("token\t\tid\t\tsecret\t\tattempted")
while(rs.next()) {
val token = rs.getInt("token")
val id = rs.getString("id")
val secret = rs.getString("secret")
val attempted = rs.getString("attempted")
println(s"${token}\t\t${id}\t\t${secret}\t\t${attempted}\n\n")
}
val rss: ResultSet = Statements.tlStmts.get.getMapIdTable.executeQuery()
println("uuid\t\ttoken\t\tlastServed")
while(rss.next()){
val uuid = rss.getString("uuid")
val token = rss.getInt("token")
val lastServed = rss.getTimestamp("lastServed")
println(s"${uuid}\t\t${token}\t\t${lastServed}\n\n")
}
}
}

View File

@ -0,0 +1,38 @@
package lc.core
import lc.captchas._
import lc.captchas.interfaces.ChallengeProvider
object CaptchaProviders {
private val providers = Map(
"FilterChallenge" -> new FilterChallenge,
//"FontFunCaptcha" -> new FontFunCaptcha,
"GifCaptcha" -> new GifCaptcha,
"ShadowTextCaptcha" -> new ShadowTextCaptcha,
"RainDropsCaptcha" -> new RainDropsCP,
//"LabelCaptcha" -> new LabelCaptcha
)
def generateChallengeSamples() = {
providers.map {case (key, provider) =>
(key, provider.returnChallenge())
}
}
private val seed = System.currentTimeMillis.toString.substring(2,6).toInt
private val random = new scala.util.Random(seed)
private def getNextRandomInt(max: Int) = random.synchronized {
random.nextInt(max)
}
def getProviderById(id: String): ChallengeProvider = {
return providers(id)
}
def getProvider(): ChallengeProvider = {
val keys = providers.keys
val providerIndex = keys.toVector(getNextRandomInt(keys.size))
providers(providerIndex)
}
}

View File

@ -0,0 +1,7 @@
package lc.core
case class Size(height: Int, width: Int)
case class Parameters(level: String, media: String, input_type: String, size: Option[Size])
case class Id(id: String)
case class Answer(answer: String, id: String)
case class Result(result: String)

View File

@ -1,4 +1,4 @@
package lc package lc.database
import java.sql._ import java.sql._

View File

@ -0,0 +1,31 @@
package lc.database
import lc.database.DBConn
import java.sql.Statement
class Statements(dbConn: DBConn) {
private val stmt = dbConn.getStatement()
stmt.execute("CREATE TABLE IF NOT EXISTS challenge(token int auto_increment, id varchar, secret varchar, provider varchar, contentType varchar, image blob, attempted int default 0, PRIMARY KEY(token))")
stmt.execute("CREATE TABLE IF NOT EXISTS mapId(uuid varchar, token int, lastServed timestamp, PRIMARY KEY(uuid), FOREIGN KEY(token) REFERENCES challenge(token) ON DELETE CASCADE)")
val insertPstmt = dbConn.con.prepareStatement("INSERT INTO challenge(id, secret, provider, contentType, image) VALUES (?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS )
val mapPstmt = dbConn.con.prepareStatement("INSERT INTO mapId(uuid, token, lastServed) VALUES (?, ?, CURRENT_TIMESTAMP)")
val selectPstmt = dbConn.con.prepareStatement("SELECT c.secret, c.provider FROM challenge c, mapId m WHERE m.token=c.token AND DATEDIFF(MINUTE, CURRENT_TIMESTAMP, DATEADD(MINUTE, 1, m.lastServed)) > 0 AND m.uuid = ?")
val imagePstmt = dbConn.con.prepareStatement("SELECT image FROM challenge c, mapId m WHERE c.token=m.token AND m.uuid = ?")
val updateAttemptedPstmt = dbConn.con.prepareStatement("UPDATE challenge SET attempted = attempted+1 WHERE token = (SELECT m.token FROM mapId m, challenge c WHERE m.token=c.token AND m.uuid = ?)")
val tokenPstmt = dbConn.con.prepareStatement("SELECT token FROM challenge WHERE attempted < 10 ORDER BY RAND() LIMIT 1")
val deleteAnswerPstmt = dbConn.con.prepareStatement("DELETE FROM mapId WHERE uuid = ?")
val challengeGCPstmt = dbConn.con.prepareStatement("DELETE FROM challenge WHERE attempted >= 10 AND token NOT IN (SELECT token FROM mapId)")
val mapIdGCPstmt = dbConn.con.prepareStatement("DELETE FROM mapId WHERE DATEDIFF(MINUTE, CURRENT_TIMESTAMP, DATEADD(MINUTE, 1, lastServed)) < 0")
val getCountChallengeTable = dbConn.con.prepareStatement("SELECT COUNT(*) AS total FROM challenge")
val getChallengeTable = dbConn.con.prepareStatement("SELECT * FROM challenge")
val getMapIdTable = dbConn.con.prepareStatement("SELECT * FROM mapId")
}
object Statements {
private val dbConn: DBConn = new DBConn()
val tlStmts = ThreadLocal.withInitial(() => new Statements(dbConn))
}

View File

@ -1,15 +1,14 @@
package lc package lc.server
import java.io.File import org.json4s.DefaultFormats
import org.json4s._ import org.json4s.jackson.JsonMethods.parse
import org.json4s.jackson.JsonMethods._ import org.json4s.jackson.Serialization.write
import org.json4s.jackson.Serialization.{read, write} import lc.core.Captcha
import lc.core.{Parameters, Id, Answer}
import lc.server.HTTPServer
import lc.HTTPServer._
case class Secret(token: Int) class Server(port: Int, captcha: Captcha){
class Server(port: Int, captcha: Captcha, dbConn: DBConn){
val server = new HTTPServer(port) val server = new HTTPServer(port)
val host = server.getVirtualHost(null) val host = server.getVirtualHost(null)
@ -40,8 +39,7 @@ class Server(port: Int, captcha: Captcha, dbConn: DBConn){
val answer = json.extract[Answer] val answer = json.extract[Answer]
val result = captcha.checkAnswer(answer) val result = captcha.checkAnswer(answer)
resp.getHeaders().add("Content-Type","application/json") resp.getHeaders().add("Content-Type","application/json")
val responseContent = s"""{"result":"$result"}""" resp.send(200, write(result))
resp.send(200,responseContent)
0 0
},"POST") },"POST")