mirror of
https://github.com/librecaptcha/lc-core.git
synced 2025-05-23 10:31:46 -04:00
respect size and level parameters
* Add size and level parameters to ChallengeProvider.returnChallenge() * Add size column to challenge table * Pass size and level parameters to all relevant calls * Add size field to demo app
This commit is contained in:
parent
f0659da3eb
commit
edd211fb52
@ -81,7 +81,7 @@ public class FontFunCaptcha implements ChallengeProvider {
|
|||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Challenge returnChallenge() {
|
public Challenge returnChallenge(String level, String size) {
|
||||||
String secret = HelperFunctions.randomString(7);
|
String secret = HelperFunctions.randomString(7);
|
||||||
String path = "./lib/fonts/";
|
String path = "./lib/fonts/";
|
||||||
return new Challenge(fontFun(secret, "medium", path), "image/png", secret.toLowerCase());
|
return new Challenge(fontFun(secret, "medium", path), "image/png", secret.toLowerCase());
|
||||||
|
@ -100,7 +100,7 @@ public class PoppingCharactersCaptcha implements ChallengeProvider {
|
|||||||
"supportedInputType", List.of("text"));
|
"supportedInputType", List.of("text"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Challenge returnChallenge() {
|
public Challenge returnChallenge(String level, String size) {
|
||||||
final var secret = HelperFunctions.randomString(6);
|
final var secret = HelperFunctions.randomString(6);
|
||||||
return new Challenge(gifCaptcha(secret), "image/gif", secret.toLowerCase());
|
return new Challenge(gifCaptcha(secret), "image/gif", secret.toLowerCase());
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ public class ShadowTextCaptcha implements ChallengeProvider {
|
|||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Challenge returnChallenge() {
|
public Challenge returnChallenge(String level, String size) {
|
||||||
String secret = HelperFunctions.randomString(6);
|
String secret = HelperFunctions.randomString(6);
|
||||||
return new Challenge(shadowText(secret), "image/png", secret.toLowerCase());
|
return new Challenge(shadowText(secret), "image/png", secret.toLowerCase());
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import java.util.List;
|
|||||||
public interface ChallengeProvider {
|
public interface ChallengeProvider {
|
||||||
public String getId();
|
public String getId();
|
||||||
|
|
||||||
public Challenge returnChallenge();
|
public Challenge returnChallenge(String level, String size);
|
||||||
|
|
||||||
public boolean checkAnswer(String secret, String answer);
|
public boolean checkAnswer(String secret, String answer);
|
||||||
|
|
||||||
|
@ -20,9 +20,10 @@
|
|||||||
const levelInput = document.getElementById("levelInput").value
|
const levelInput = document.getElementById("levelInput").value
|
||||||
const mediaInput = document.getElementById("mediaInput").value
|
const mediaInput = document.getElementById("mediaInput").value
|
||||||
const typeInput = document.getElementById("typeInput").value
|
const typeInput = document.getElementById("typeInput").value
|
||||||
fetch("/v1/captcha", {
|
const sizeInput = document.getElementById("sizeInput").value
|
||||||
|
fetch("/v2/captcha", {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({level: levelInput, media: mediaInput, "input_type" : typeInput})
|
body: JSON.stringify({level: levelInput, media: mediaInput, "input_type" : typeInput, "size": sizeInput})
|
||||||
}).then(async function(resp) {
|
}).then(async function(resp) {
|
||||||
const respJson = await resp.json()
|
const respJson = await resp.json()
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
||||||
@ -30,7 +31,7 @@
|
|||||||
const resultDiv = document.getElementById("result")
|
const resultDiv = document.getElementById("result")
|
||||||
const result = `
|
const result = `
|
||||||
<p>Id: ${id}</p>
|
<p>Id: ${id}</p>
|
||||||
<p><img src="/v1/media?id=${id}" /> </p>
|
<p><img src="/v2/media?id=${id}" /> </p>
|
||||||
<input type="text" id="answerInput" />
|
<input type="text" id="answerInput" />
|
||||||
<button onClick="submitAnswer('${id}')">Submit</button>
|
<button onClick="submitAnswer('${id}')">Submit</button>
|
||||||
<div id="answerResult" />
|
<div id="answerResult" />
|
||||||
@ -43,7 +44,7 @@
|
|||||||
}
|
}
|
||||||
async function submitAnswer(id) {
|
async function submitAnswer(id) {
|
||||||
const ans = document.getElementById("answerInput").value;
|
const ans = document.getElementById("answerInput").value;
|
||||||
const resp = await fetch("/v1/answer", {
|
const resp = await fetch("/v2/answer", {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({id: id, answer: ans})
|
body: JSON.stringify({id: id, answer: ans})
|
||||||
})
|
})
|
||||||
@ -70,6 +71,10 @@
|
|||||||
<span>Input Type</span>
|
<span>Input Type</span>
|
||||||
<input type="text" id="typeInput" value="text" />
|
<input type="text" id="typeInput" value="text" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inputGroup">
|
||||||
|
<span>Input Size</span>
|
||||||
|
<input type="text" id="sizeInput" value="150x100" />
|
||||||
|
</div>
|
||||||
<div class="inputGroup">
|
<div class="inputGroup">
|
||||||
<button onClick="loadCaptcha()">Get New CAPTCHA</button>
|
<button onClick="loadCaptcha()">Get New CAPTCHA</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,8 +45,10 @@ class BackgroundTask(config: Config, captchaManager: CaptchaManager) {
|
|||||||
(config.captchaConfig).flatMap {captcha =>
|
(config.captchaConfig).flatMap {captcha =>
|
||||||
(captcha.allowedLevels).flatMap {level =>
|
(captcha.allowedLevels).flatMap {level =>
|
||||||
(captcha.allowedMedia).flatMap {media =>
|
(captcha.allowedMedia).flatMap {media =>
|
||||||
(captcha.allowedInputType).map {inputType =>
|
(captcha.allowedInputType).flatMap {inputType =>
|
||||||
Parameters(level, media, inputType, Some(Size(0, 0)))
|
(captcha.allowedSizes).map {size =>
|
||||||
|
Parameters(level, media, inputType, size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,8 +60,9 @@ class BackgroundTask(config: Config, captchaManager: CaptchaManager) {
|
|||||||
val level = pickRandom(captcha.allowedLevels)
|
val level = pickRandom(captcha.allowedLevels)
|
||||||
val media = pickRandom(captcha.allowedMedia)
|
val media = pickRandom(captcha.allowedMedia)
|
||||||
val inputType = pickRandom(captcha.allowedInputType)
|
val inputType = pickRandom(captcha.allowedInputType)
|
||||||
|
val size = pickRandom(captcha.allowedSizes)
|
||||||
|
|
||||||
Parameters(level, media, inputType, Some(Size(0, 0)))
|
Parameters(level, media, inputType, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def pickRandom[T](list: List[T]): T = {
|
private def pickRandom[T](list: List[T]): T = {
|
||||||
|
@ -66,7 +66,7 @@ class DebugCaptcha extends ChallengeProvider {
|
|||||||
baos.toByteArray()
|
baos.toByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
def returnChallenge(): Challenge = {
|
def returnChallenge(level: String, size: String): Challenge = {
|
||||||
val secret = HelperFunctions.randomString(6, HelperFunctions.safeAlphabets)
|
val secret = HelperFunctions.randomString(6, HelperFunctions.safeAlphabets)
|
||||||
new Challenge(simpleText(secret), "image/png", secret.toLowerCase())
|
new Challenge(simpleText(secret), "image/png", secret.toLowerCase())
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class FilterChallenge extends ChallengeProvider {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def returnChallenge(): Challenge = {
|
def returnChallenge(level: String, size: String): Challenge = {
|
||||||
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"
|
||||||
|
@ -40,7 +40,7 @@ class LabelCaptcha extends ChallengeProvider {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def returnChallenge(): Challenge =
|
def returnChallenge(level: String, size: String): Challenge =
|
||||||
synchronized {
|
synchronized {
|
||||||
val r = scala.util.Random.nextInt(knownFiles.length)
|
val r = scala.util.Random.nextInt(knownFiles.length)
|
||||||
val s = scala.util.Random.nextInt(unknownFiles.length)
|
val s = scala.util.Random.nextInt(unknownFiles.length)
|
||||||
|
@ -56,7 +56,7 @@ class RainDropsCP extends ChallengeProvider {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
def returnChallenge(): Challenge = {
|
def returnChallenge(level: String, size: String): Challenge = {
|
||||||
val r = new scala.util.Random
|
val r = new scala.util.Random
|
||||||
val secret = LazyList.continually(r.nextInt(alphabet.size)).map(alphabet).take(n).mkString
|
val secret = LazyList.continually(r.nextInt(alphabet.size)).map(alphabet).take(n).mkString
|
||||||
val width = 450
|
val width = 450
|
||||||
|
@ -10,7 +10,7 @@ object ParametersEnum extends Enumeration {
|
|||||||
val ALLOWEDLEVELS: Value = Value("allowedLevels")
|
val ALLOWEDLEVELS: Value = Value("allowedLevels")
|
||||||
val ALLOWEDMEDIA: Value = Value("allowedMedia")
|
val ALLOWEDMEDIA: Value = Value("allowedMedia")
|
||||||
val ALLOWEDINPUTTYPE: Value = Value("allowedInputType")
|
val ALLOWEDINPUTTYPE: Value = Value("allowedInputType")
|
||||||
|
val ALLOWEDSIZES: Value = Value("allowedSizes")
|
||||||
}
|
}
|
||||||
|
|
||||||
object AttributesEnum extends Enumeration {
|
object AttributesEnum extends Enumeration {
|
||||||
|
@ -36,11 +36,11 @@ class CaptchaManager(config: Config, captchaProviders: CaptchaProviders) {
|
|||||||
def generateChallenge(param: Parameters): Option[Int] = {
|
def generateChallenge(param: Parameters): Option[Int] = {
|
||||||
captchaProviders.getProvider(param).flatMap { provider =>
|
captchaProviders.getProvider(param).flatMap { provider =>
|
||||||
val providerId = provider.getId()
|
val providerId = provider.getId()
|
||||||
val challenge = provider.returnChallenge()
|
val challenge = provider.returnChallenge(param.level, param.size)
|
||||||
val blob = new ByteArrayInputStream(challenge.content)
|
val blob = new ByteArrayInputStream(challenge.content)
|
||||||
val token = insertCaptcha(provider, challenge, providerId, param, blob)
|
val token = insertCaptcha(provider, challenge, providerId, param, blob)
|
||||||
// println("Added new challenge: " + token.toString)
|
// println("Added new challenge: " + token.toString)
|
||||||
token.map(_.toInt)
|
token.map(_.toInt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +58,8 @@ class CaptchaManager(config: Config, captchaProviders: CaptchaProviders) {
|
|||||||
insertPstmt.setString(4, challenge.contentType)
|
insertPstmt.setString(4, challenge.contentType)
|
||||||
insertPstmt.setString(5, param.level)
|
insertPstmt.setString(5, param.level)
|
||||||
insertPstmt.setString(6, param.input_type)
|
insertPstmt.setString(6, param.input_type)
|
||||||
insertPstmt.setBlob(7, blob)
|
insertPstmt.setString(7, param.size)
|
||||||
|
insertPstmt.setBlob(8, blob)
|
||||||
insertPstmt.executeUpdate()
|
insertPstmt.executeUpdate()
|
||||||
val rs: ResultSet = insertPstmt.getGeneratedKeys()
|
val rs: ResultSet = insertPstmt.getGeneratedKeys()
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
@ -106,6 +107,7 @@ class CaptchaManager(config: Config, captchaProviders: CaptchaProviders) {
|
|||||||
countPstmt.setString(1, param.level)
|
countPstmt.setString(1, param.level)
|
||||||
countPstmt.setString(2, param.media)
|
countPstmt.setString(2, param.media)
|
||||||
countPstmt.setString(3, param.input_type)
|
countPstmt.setString(3, param.input_type)
|
||||||
|
countPstmt.setString(4, param.size.toString())
|
||||||
val rs = countPstmt.executeQuery()
|
val rs = countPstmt.executeQuery()
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
Some(rs.getInt("count"))
|
Some(rs.getInt("count"))
|
||||||
@ -123,7 +125,8 @@ class CaptchaManager(config: Config, captchaProviders: CaptchaProviders) {
|
|||||||
tokenPstmt.setString(1, param.level)
|
tokenPstmt.setString(1, param.level)
|
||||||
tokenPstmt.setString(2, param.media)
|
tokenPstmt.setString(2, param.media)
|
||||||
tokenPstmt.setString(3, param.input_type)
|
tokenPstmt.setString(3, param.input_type)
|
||||||
tokenPstmt.setInt(4, count)
|
tokenPstmt.setString(4, param.size)
|
||||||
|
tokenPstmt.setInt(5, count)
|
||||||
val rs = tokenPstmt.executeQuery()
|
val rs = tokenPstmt.executeQuery()
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
Some(rs.getInt("token"))
|
Some(rs.getInt("token"))
|
||||||
|
@ -19,7 +19,7 @@ class CaptchaProviders(config: Config) {
|
|||||||
|
|
||||||
def generateChallengeSamples(): Map[String, Challenge] = {
|
def generateChallengeSamples(): Map[String, Challenge] = {
|
||||||
providers.map { case (key, provider) =>
|
providers.map { case (key, provider) =>
|
||||||
(key, provider.returnChallenge())
|
(key, provider.returnChallenge("easy", "350x100"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,6 +35,7 @@ class CaptchaProviders(config: Config) {
|
|||||||
if configValue.allowedLevels.contains(param.level)
|
if configValue.allowedLevels.contains(param.level)
|
||||||
if configValue.allowedMedia.contains(param.media)
|
if configValue.allowedMedia.contains(param.media)
|
||||||
if configValue.allowedInputType.contains(param.input_type)
|
if configValue.allowedInputType.contains(param.input_type)
|
||||||
|
if configValue.allowedSizes.contains(param.size)
|
||||||
} yield (configValue.name, configValue.config)
|
} yield (configValue.name, configValue.config)
|
||||||
|
|
||||||
val providerFilter = for {
|
val providerFilter = for {
|
||||||
|
@ -81,6 +81,7 @@ class Config(configFilePath: String) {
|
|||||||
(ParametersEnum.ALLOWEDLEVELS.toString -> List("medium", "hard")) ~
|
(ParametersEnum.ALLOWEDLEVELS.toString -> List("medium", "hard")) ~
|
||||||
(ParametersEnum.ALLOWEDMEDIA.toString -> List("image/png")) ~
|
(ParametersEnum.ALLOWEDMEDIA.toString -> List("image/png")) ~
|
||||||
(ParametersEnum.ALLOWEDINPUTTYPE.toString -> List("text")) ~
|
(ParametersEnum.ALLOWEDINPUTTYPE.toString -> List("text")) ~
|
||||||
|
(ParametersEnum.ALLOWEDSIZES.toString -> List("350x100")) ~
|
||||||
(AttributesEnum.CONFIG.toString -> JObject())
|
(AttributesEnum.CONFIG.toString -> JObject())
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -88,6 +89,7 @@ class Config(configFilePath: String) {
|
|||||||
(ParametersEnum.ALLOWEDLEVELS.toString -> List("hard")) ~
|
(ParametersEnum.ALLOWEDLEVELS.toString -> List("hard")) ~
|
||||||
(ParametersEnum.ALLOWEDMEDIA.toString -> List("image/gif")) ~
|
(ParametersEnum.ALLOWEDMEDIA.toString -> List("image/gif")) ~
|
||||||
(ParametersEnum.ALLOWEDINPUTTYPE.toString -> List("text")) ~
|
(ParametersEnum.ALLOWEDINPUTTYPE.toString -> List("text")) ~
|
||||||
|
(ParametersEnum.ALLOWEDSIZES.toString -> List("350x100")) ~
|
||||||
(AttributesEnum.CONFIG.toString -> JObject())
|
(AttributesEnum.CONFIG.toString -> JObject())
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -95,6 +97,7 @@ class Config(configFilePath: String) {
|
|||||||
(ParametersEnum.ALLOWEDLEVELS.toString -> List("easy")) ~
|
(ParametersEnum.ALLOWEDLEVELS.toString -> List("easy")) ~
|
||||||
(ParametersEnum.ALLOWEDMEDIA.toString -> List("image/png")) ~
|
(ParametersEnum.ALLOWEDMEDIA.toString -> List("image/png")) ~
|
||||||
(ParametersEnum.ALLOWEDINPUTTYPE.toString -> List("text")) ~
|
(ParametersEnum.ALLOWEDINPUTTYPE.toString -> List("text")) ~
|
||||||
|
(ParametersEnum.ALLOWEDSIZES.toString -> List("350x100")) ~
|
||||||
(AttributesEnum.CONFIG.toString -> JObject())
|
(AttributesEnum.CONFIG.toString -> JObject())
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
@ -102,6 +105,7 @@ class Config(configFilePath: String) {
|
|||||||
(ParametersEnum.ALLOWEDLEVELS.toString -> List("easy", "medium")) ~
|
(ParametersEnum.ALLOWEDLEVELS.toString -> List("easy", "medium")) ~
|
||||||
(ParametersEnum.ALLOWEDMEDIA.toString -> List("image/gif")) ~
|
(ParametersEnum.ALLOWEDMEDIA.toString -> List("image/gif")) ~
|
||||||
(ParametersEnum.ALLOWEDINPUTTYPE.toString -> List("text")) ~
|
(ParametersEnum.ALLOWEDINPUTTYPE.toString -> List("text")) ~
|
||||||
|
(ParametersEnum.ALLOWEDSIZES.toString -> List("350x100")) ~
|
||||||
(AttributesEnum.CONFIG.toString -> JObject())
|
(AttributesEnum.CONFIG.toString -> JObject())
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
@ -4,8 +4,9 @@ import org.json4s.jackson.Serialization.write
|
|||||||
import lc.core.Config.formats
|
import lc.core.Config.formats
|
||||||
|
|
||||||
trait ByteConvert { def toBytes(): Array[Byte] }
|
trait ByteConvert { def toBytes(): Array[Byte] }
|
||||||
|
// case class Size(height: Int, width: Int)
|
||||||
case class Size(height: Int, width: Int)
|
case class Size(height: Int, width: Int)
|
||||||
case class Parameters(level: String, media: String, input_type: String, size: Option[Size])
|
case class Parameters(level: String, media: String, input_type: String, size: String)
|
||||||
case class Id(id: String) extends ByteConvert { def toBytes(): Array[Byte] = { write(this).getBytes } }
|
case class Id(id: String) extends ByteConvert { def toBytes(): Array[Byte] = { write(this).getBytes } }
|
||||||
case class Image(image: Array[Byte]) extends ByteConvert { def toBytes(): Array[Byte] = { image } }
|
case class Image(image: Array[Byte]) extends ByteConvert { def toBytes(): Array[Byte] = { image } }
|
||||||
case class Answer(answer: String, id: String)
|
case class Answer(answer: String, id: String)
|
||||||
@ -16,6 +17,7 @@ case class CaptchaConfig(
|
|||||||
allowedLevels: List[String],
|
allowedLevels: List[String],
|
||||||
allowedMedia: List[String],
|
allowedMedia: List[String],
|
||||||
allowedInputType: List[String],
|
allowedInputType: List[String],
|
||||||
|
allowedSizes: List[String],
|
||||||
config: String
|
config: String
|
||||||
)
|
)
|
||||||
case class ConfigField(
|
case class ConfigField(
|
||||||
|
@ -3,7 +3,7 @@ package lc.database
|
|||||||
import java.sql.{Connection, DriverManager, Statement}
|
import java.sql.{Connection, DriverManager, Statement}
|
||||||
|
|
||||||
class DBConn() {
|
class DBConn() {
|
||||||
val con: Connection = DriverManager.getConnection("jdbc:h2:./data/H2/captcha2;MAX_COMPACT_TIME=8000;DB_CLOSE_ON_EXIT=FALSE", "sa", "")
|
val con: Connection = DriverManager.getConnection("jdbc:h2:./data/H2/captcha3;MAX_COMPACT_TIME=8000;DB_CLOSE_ON_EXIT=FALSE", "sa", "")
|
||||||
|
|
||||||
def getStatement(): Statement = {
|
def getStatement(): Statement = {
|
||||||
con.createStatement()
|
con.createStatement()
|
||||||
|
@ -17,6 +17,7 @@ class Statements(dbConn: DBConn, maxAttempts: Int) {
|
|||||||
"contentType varchar, " +
|
"contentType varchar, " +
|
||||||
"contentLevel varchar, " +
|
"contentLevel varchar, " +
|
||||||
"contentInput varchar, " +
|
"contentInput varchar, " +
|
||||||
|
"size varchar, " +
|
||||||
"image blob, " +
|
"image blob, " +
|
||||||
"attempted int default 0, " +
|
"attempted int default 0, " +
|
||||||
"PRIMARY KEY(token));" +
|
"PRIMARY KEY(token));" +
|
||||||
@ -37,8 +38,8 @@ class Statements(dbConn: DBConn, maxAttempts: Int) {
|
|||||||
|
|
||||||
val insertPstmt: PreparedStatement = dbConn.con.prepareStatement(
|
val insertPstmt: PreparedStatement = dbConn.con.prepareStatement(
|
||||||
"INSERT INTO " +
|
"INSERT INTO " +
|
||||||
"challenge(id, secret, provider, contentType, contentLevel, contentInput, image) " +
|
"challenge(id, secret, provider, contentType, contentLevel, contentInput, size, image) " +
|
||||||
"VALUES (?, ?, ?, ?, ?, ?, ?)",
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
Statement.RETURN_GENERATED_KEYS
|
Statement.RETURN_GENERATED_KEYS
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,7 +78,8 @@ class Statements(dbConn: DBConn, maxAttempts: Int) {
|
|||||||
WHERE attempted < $maxAttempts AND
|
WHERE attempted < $maxAttempts AND
|
||||||
contentLevel = ? AND
|
contentLevel = ? AND
|
||||||
contentType = ? AND
|
contentType = ? AND
|
||||||
contentInput = ?
|
contentInput = ? AND
|
||||||
|
size = ?
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -88,7 +90,8 @@ class Statements(dbConn: DBConn, maxAttempts: Int) {
|
|||||||
WHERE attempted < $maxAttempts AND
|
WHERE attempted < $maxAttempts AND
|
||||||
contentLevel = ? AND
|
contentLevel = ? AND
|
||||||
contentType = ? AND
|
contentType = ? AND
|
||||||
contentInput = ?
|
contentInput = ? AND
|
||||||
|
size = ?
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
OFFSET FLOOR(RAND()*?)
|
OFFSET FLOOR(RAND()*?)
|
||||||
"""
|
"""
|
||||||
|
@ -23,7 +23,7 @@ class Server(address: String, port: Int, captchaManager: CaptchaManager, playgro
|
|||||||
.address(new InetSocketAddress(address, port))
|
.address(new InetSocketAddress(address, port))
|
||||||
.backlog(32)
|
.backlog(32)
|
||||||
.POST(
|
.POST(
|
||||||
"/v1/captcha",
|
"/v2/captcha",
|
||||||
(request) => {
|
(request) => {
|
||||||
val json = parse(request.getBodyString())
|
val json = parse(request.getBodyString())
|
||||||
val param = json.extract[Parameters]
|
val param = json.extract[Parameters]
|
||||||
@ -32,7 +32,7 @@ class Server(address: String, port: Int, captchaManager: CaptchaManager, playgro
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.GET(
|
.GET(
|
||||||
"/v1/media",
|
"/v2/media",
|
||||||
(request) => {
|
(request) => {
|
||||||
val params = request.getQueryParams()
|
val params = request.getQueryParams()
|
||||||
val result = if (params.containsKey("id")) {
|
val result = if (params.containsKey("id")) {
|
||||||
@ -46,7 +46,7 @@ class Server(address: String, port: Int, captchaManager: CaptchaManager, playgro
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.POST(
|
.POST(
|
||||||
"/v1/answer",
|
"/v2/answer",
|
||||||
(request) => {
|
(request) => {
|
||||||
val json = parse(request.getBodyString())
|
val json = parse(request.getBodyString())
|
||||||
val answer = json.extract[Answer]
|
val answer = json.extract[Answer]
|
||||||
@ -70,7 +70,7 @@ class Server(address: String, port: Int, captchaManager: CaptchaManager, playgro
|
|||||||
<html>
|
<html>
|
||||||
<h2>Welcome to LibreCaptcha server</h2>
|
<h2>Welcome to LibreCaptcha server</h2>
|
||||||
<h3><a href="/demo/index.html">Link to Demo</a></h3>
|
<h3><a href="/demo/index.html">Link to Demo</a></h3>
|
||||||
<h3>API is served at <b>/v1/</b></h3>
|
<h3>API is served at <b>/v2/</b></h3>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
new StringResponse(200, str)
|
new StringResponse(200, str)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user