librecaptcha/src/main/scala/lc/core/captcha.scala

156 lines
4.9 KiB
Scala

package lc.core
import java.sql.{Blob, ResultSet}
import java.util.UUID
import java.io.ByteArrayInputStream
import lc.database.Statements
import lc.core.CaptchaProviders
import lc.captchas.interfaces.ChallengeProvider
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 = {
val provider = CaptchaProviders.getProvider(param)
if (!provider.isInstanceOf[ChallengeProvider]) return -1
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.setString(5, param.level)
insertPstmt.setString(6, param.input_type)
insertPstmt.setBlob(7, 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 allowedInputType = Config.allowedInputType
val allowedLevels = Config.allowedLevels
val allowedMedia = Config.allowedMedia
private def validateParam(param: Parameters): Boolean = {
if (
allowedLevels.contains(param.level) &&
allowedMedia.contains(param.media) &&
allowedInputType.contains(param.input_type)
)
return true
else
return false
}
def getChallenge(param: Parameters): ChallengeResult = {
try {
val validParam = validateParam(param)
if (validParam) {
val tokenPstmt = Statements.tlStmts.get.tokenPstmt
tokenPstmt.setString(1, param.level)
tokenPstmt.setString(2, param.media)
tokenPstmt.setString(3, param.input_type)
val rs = tokenPstmt.executeQuery()
val tokenOpt = if (rs.next()) {
Some(rs.getInt("token"))
} else {
None
}
val updateAttemptedPstmt = Statements.tlStmts.get.updateAttemptedPstmt
val token = tokenOpt.getOrElse(generateChallenge(param))
val result = if (token != -1) {
val uuid = getUUID(token)
updateAttemptedPstmt.setString(1, uuid)
updateAttemptedPstmt.executeUpdate()
Id(uuid)
} else {
Error(ErrorMessageEnum.NO_CAPTCHA.toString)
}
result
} else {
Error(ErrorMessageEnum.INVALID_PARAM.toString)
}
} catch {
case e: Exception =>
println(e)
Error(ErrorMessageEnum.SMW.toString)
}
}
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.setInt(1, Config.captchaExpiryTimeLimit)
selectPstmt.setString(2, 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) ResultEnum.TRUE.toString else ResultEnum.FALSE.toString
result
} else {
ResultEnum.EXPIRED.toString
}
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")
}
}
}