Friendly, easy, lightweight, self-hostable CAPTCHA service. https://captcheck.netsyms.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

api.php 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <?php
  2. require __DIR__ . '/required.php';
  3. header("Content-Type: application/json");
  4. // Oldest session allowed
  5. $session_min_date = date("Y-m-d H:i:s", strtotime("-" . SESSION_EXPIRE_MINUTES . " minutes"));
  6. // Delete old sessions
  7. $old_sessions = $database->select("sessions", "sid", ["timestamp[<]" => $session_min_date]);
  8. $database->delete("scrambled_answers", ["sid" => $old_sessions]);
  9. $database->delete("sessions", ["sid" => $old_sessions]);
  10. switch ($VARS['action']) {
  11. case "ping":
  12. $out = ["status" => "OK", "pong" => true];
  13. exit(json_encode($out));
  14. case "new":
  15. // generate unique session ID that has an essentially zero chance of being a duplicate.
  16. // Contains a hash of a secure random number, a hash of the user's IP, and 23 uniqid() characters.
  17. $skey = uniqid(substr(hash("md5", mt_rand()), 3, 5) . hash("md5", getUserIP()), true);
  18. $answers = $database->select('answers', ['aid', 'aname']);
  19. shuffle($answers);
  20. $answers = array_slice($answers, 0, 5);
  21. //var_dump($answers);
  22. $correct_answer = $answers[mt_rand(0, count($answers) - 1)];
  23. $scrambled = ["real" => [], "fake" => []];
  24. foreach ($answers as $a) {
  25. $scrambled["real"][] = $a['aid'];
  26. $scrambled["fake"][] = substr(hash("md5", mt_rand()), 0, 20);
  27. }
  28. $database->insert("sessions", ["skey" => $skey, "aid" => $correct_answer['aid'], "expired" => 0, "#timestamp" => "NOW()", "ipaddr" => getUserIP()]);
  29. $sid = $database->id();
  30. $scrambled_insert = [];
  31. for ($i = 0; $i < count($scrambled['real']); $i++) {
  32. $scrambled_insert[] = ["sid" => $sid, "aid" => $scrambled['real'][$i], "acode" => $scrambled['fake'][$i]];
  33. }
  34. $database->insert("scrambled_answers", $scrambled_insert);
  35. $questions = ["Please click on the [].", "Click the [].", "Find the []."];
  36. $accessible_questions = ["Please type [] here.", "Enter [] into the box.", "Type []."];
  37. shuffle($questions);
  38. shuffle($accessible_questions);
  39. $resp = [
  40. "session" => $skey,
  41. "id_prefix" => substr(hash("md5", mt_rand()), 3, 5),
  42. "question_i" => str_replace("[]", $correct_answer['aname'], $questions[0]),
  43. "question_a" => str_replace("[]", $correct_answer['aname'], $accessible_questions[0]),
  44. "answers" => $scrambled["fake"]
  45. ];
  46. exit(json_encode($resp));
  47. case "img":
  48. if (!$database->has('sessions', ['skey' => $VARS['s']])) {
  49. sendError("Missing or invalid session ID.", "client");
  50. }
  51. $sid = $database->get('sessions', 'sid', ['skey' => $VARS['s']]);
  52. if (!$database->has("scrambled_answers", ["AND" => ["sid" => $sid, "acode" => $VARS['c']]])) {
  53. sendError("Missing or invalid image code.", "client");
  54. }
  55. $imgid = $database->get("scrambled_answers", ["[>]answers" => ["aid" => "aid"]], 'aimg', ["AND" => ["sid" => $sid, "acode" => $VARS['c']]]);
  56. /* Load image, add some black/white noise, and send */
  57. header('Content-Type: image/png');
  58. $imgpath = __DIR__ . "/images/" . $imgid . ".png";
  59. if (DEBUG) {
  60. file_put_contents("debug", $imgpath . "\n", FILE_APPEND);
  61. }
  62. $img = imagecreatefrompng($imgpath);
  63. imageAlphaBlending($img, true);
  64. imageSaveAlpha($img, true);
  65. $black = imagecolorallocate($img, 0, 0, 0);
  66. $white = imagecolorallocate($img, 255, 255, 255);
  67. // Add static noise
  68. for ($i = 0; $i < 150; $i++) {
  69. imagesetpixel($img, mt_rand(0, 63), mt_rand(0, 63), $black);
  70. }
  71. for ($i = 0; $i < 75; $i++) {
  72. imagesetpixel($img, mt_rand(0, 63), mt_rand(0, 63), $white);
  73. }
  74. // Add lines
  75. for ($i = 0; $i < 2; $i++) {
  76. imageline($img, mt_rand(0, 63), mt_rand(0, 63), mt_rand(0, 63), mt_rand(0, 63), $black);
  77. }
  78. for ($i = 0; $i < 5; $i++) {
  79. imageline($img, mt_rand(0, 63), mt_rand(0, 63), mt_rand(0, 63), mt_rand(0, 63), $white);
  80. }
  81. imagepng($img);
  82. exit();
  83. case "verify":
  84. if (!$database->has('sessions', ['skey' => $VARS['session_id']])) {
  85. echo json_encode(["session" => $VARS['session_id'], "result" => false, "msg" => "Session invalid."]);
  86. exit();
  87. }
  88. $sid = $database->get('sessions', 'sid', ['skey' => $VARS['session_id']]);
  89. $expired = ($database->get('sessions', 'expired', ['skey' => $VARS['session_id']]) == 1 ? true : false);
  90. if ($expired) {
  91. echo json_encode(["session" => $VARS['session_id'], "result" => false, "msg" => "Session key already used."]);
  92. exit();
  93. }
  94. $image = false;
  95. if ($database->has("scrambled_answers", ["AND" => ["sid" => $sid, "acode" => $VARS['answer_id']]])) {
  96. // Image maybe correct
  97. $image = true;
  98. } else if ($database->has("sessions", ["[>]answers" => ["aid" => "aid"]], ["AND" => ["sid" => $sid, "aname" => $VARS['answer_id']]])) {
  99. // Accessible text correct
  100. $image = false;
  101. } else {
  102. // Invalid answer
  103. echo json_encode(["session" => $VARS['session_id'], "result" => false, "msg" => "Answer invalid."]);
  104. exit();
  105. }
  106. if ($image) {
  107. $aid = $database->get('scrambled_answers', 'aid', ["AND" => ["sid" => $sid, "acode" => $VARS['answer_id']]]);
  108. if ($database->has('sessions', ["AND" => ["sid" => $sid, "aid" => $aid]])) {
  109. echo json_encode(["session" => $VARS['session_id'], "result" => true]);
  110. } else {
  111. echo json_encode(["session" => $VARS['session_id'], "result" => false, "msg" => "Answer incorrect."]);
  112. }
  113. } else {
  114. echo json_encode(["session" => $VARS['session_id'], "result" => true]);
  115. }
  116. $database->update("sessions", ['expired' => 1], ["sid" => $sid]);
  117. exit();
  118. default:
  119. sendError("Bad Request", "client");
  120. }