1
0

captcha_gen.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <?php
  2. class captcha{
  3. public function __construct($frontend, $get, $filters, $page, $output){
  4. // check if we want captcha
  5. if(config::BOT_PROTECTION !== 1){
  6. if($output === true){
  7. $frontend->loadheader(
  8. $get,
  9. $filters,
  10. $page
  11. );
  12. }
  13. return;
  14. }
  15. /*
  16. Validate cookie, if it exists
  17. */
  18. if(isset($_COOKIE["pass"])){
  19. if(
  20. // check if key is not malformed
  21. preg_match(
  22. '/^c[0-9]+\.[A-Za-z0-9]{20}$/',
  23. $_COOKIE["pass"]
  24. ) &&
  25. // does key exist
  26. apcu_exists($_COOKIE["pass"])
  27. ){
  28. // exists, increment counter
  29. $inc = apcu_inc($_COOKIE["pass"]);
  30. // we start counting from 1
  31. // when it has been incremented to 102, it has reached
  32. // 100 reqs
  33. if($inc >= 102){
  34. // reached limit, delete and give captcha
  35. apcu_delete($_COOKIE["pass"]);
  36. }else{
  37. // the cookie is OK! dont die() and give results
  38. if($output === true){
  39. $frontend->loadheader(
  40. $get,
  41. $filters,
  42. $page
  43. );
  44. }
  45. return;
  46. }
  47. }
  48. }
  49. if($output === false){
  50. http_response_code(429); // too many reqs
  51. echo json_encode([
  52. "status" => "The \"pass\" token in your cookies is missing or has expired!!"
  53. ]);
  54. die();
  55. }
  56. /*
  57. Validate form data
  58. */
  59. $lines =
  60. explode(
  61. "\r\n",
  62. file_get_contents("php://input")
  63. );
  64. $invalid = false;
  65. $answers = [];
  66. $key = false;
  67. $error = "";
  68. foreach($lines as $line){
  69. $line = explode("=", $line, 2);
  70. if(count($line) !== 2){
  71. $invalid = true;
  72. break;
  73. }
  74. preg_match(
  75. '/^c\[([0-9]+)\]$/',
  76. $line[0],
  77. $regex
  78. );
  79. if(
  80. $line[1] != "on" ||
  81. !isset($regex[0][1])
  82. ){
  83. // check if its k
  84. if(
  85. $line[0] == "k" &&
  86. strpos($line[1], "c.") === 0
  87. ){
  88. $key = apcu_fetch($line[1]);
  89. apcu_delete($line[1]);
  90. }
  91. break;
  92. }
  93. $regex = (int)$regex[1];
  94. if(
  95. $regex >= 16 ||
  96. $regex <= -1
  97. ){
  98. $invalid = true;
  99. break;
  100. }
  101. $answers[] = $regex;
  102. }
  103. if(
  104. !$invalid &&
  105. $key !== false
  106. ){
  107. $check = $key[1];
  108. // validate answer
  109. for($i=0; $i<count($key[0]); $i++){
  110. if(!in_array($i, $answers)){
  111. continue;
  112. }
  113. if($key[0][$i][0] == $key[2]){
  114. $check--;
  115. }else{
  116. // got a wrong answer
  117. $check = -1;
  118. break;
  119. }
  120. }
  121. if($check === 0){
  122. // we passed the captcha
  123. // set cookie
  124. $inc = apcu_inc("cookie");
  125. $chars =
  126. array_merge(
  127. range("A", "Z"),
  128. range("a", "z"),
  129. range(0, 9)
  130. );
  131. $c = count($chars) - 1;
  132. $key = "c" . $inc . ".";
  133. for($i=0; $i<20; $i++){
  134. $key .= $chars[random_int(0, $c)];
  135. }
  136. apcu_inc($key, 1, $stupid, 86400);
  137. setcookie(
  138. "pass",
  139. $key,
  140. [
  141. "expires" => time() + 86400, // expires in 24 hours
  142. "samesite" => "Lax",
  143. "path" => "/"
  144. ]
  145. );
  146. $frontend->loadheader(
  147. $get,
  148. $filters,
  149. $page
  150. );
  151. return;
  152. }else{
  153. $error = "<div class=\"quote\">You were <a href=\"https://www.youtube.com/watch?v=e1d7fkQx2rk\" target=\"_BLANK\" rel=\"noreferrer nofollow\">kicked out of Mensa.</a> Please try again.</div>";
  154. }
  155. }
  156. // get the positions for the answers
  157. // will return between 3 and 6 answer positions
  158. $range = range(0, 15);
  159. $answer_pos = [];
  160. array_splice($range, 0, 1);
  161. for($i=0; $i<random_int(3, 6); $i++){
  162. $answer_pos_tmp =
  163. array_splice(
  164. $range,
  165. random_int(
  166. 0,
  167. 14 - $i
  168. ),
  169. 1
  170. );
  171. $answer_pos[] = $answer_pos_tmp[0];
  172. }
  173. // choose a dataset
  174. $c = count(config::CAPTCHA_DATASET);
  175. $choosen = config::CAPTCHA_DATASET[random_int(0, $c - 1)];
  176. $choices = [];
  177. for($i=0; $i<$c; $i++){
  178. if(config::CAPTCHA_DATASET[$i][0] == $choosen[0]){
  179. continue;
  180. }
  181. $choices[] = config::CAPTCHA_DATASET[$i];
  182. }
  183. // generate grid data
  184. $grid = [];
  185. for($i=0; $i<16; $i++){
  186. if(in_array($i, $answer_pos)){
  187. $grid[] = $choosen;
  188. }else{
  189. $grid[] = $choices[random_int(0, count($choices) - 1)];
  190. }
  191. }
  192. $key = "c." . apcu_inc("captcha_gen", 1) . "." . random_int(0, 100000000);
  193. apcu_store(
  194. $key,
  195. [
  196. $grid,
  197. count($answer_pos),
  198. $choosen[0],
  199. false // has captcha been generated?
  200. ],
  201. 120 // we give user 2 minutes to get captcha, in case of network error
  202. );
  203. $payload = [
  204. "class" => "",
  205. "right-left" => "",
  206. "right-right" => "",
  207. "left" =>
  208. '<div class="infobox">' .
  209. '<h1>IQ test</h1>' .
  210. 'Due to getting hit with 20,000 bot requests per day, I had to put this up. Sorry.<br><br>' .
  211. 'Solving this captcha will allow you to make 100 searches today. I will add a way for legit users to bypass the captcha later. Sorry /g/tards!!' .
  212. $error .
  213. '<form method="POST" enctype="text/plain" autocomplete="off">' .
  214. '<div class="captcha-wrapper">' .
  215. '<div class="captcha">' .
  216. '<img src="captcha?k=' . $key . '" alt="Captcha image">' .
  217. '<div class="captcha-controls">' .
  218. '<input type="checkbox" name="c[0]" id="c0">' .
  219. '<label for="c0"></label>' .
  220. '<input type="checkbox" name="c[1]" id="c1">' .
  221. '<label for="c1"></label>' .
  222. '<input type="checkbox" name="c[2]" id="c2">' .
  223. '<label for="c2"></label>' .
  224. '<input type="checkbox" name="c[3]" id="c3">' .
  225. '<label for="c3"></label>' .
  226. '<input type="checkbox" name="c[4]" id="c4">' .
  227. '<label for="c4"></label>' .
  228. '<input type="checkbox" name="c[5]" id="c5">' .
  229. '<label for="c5"></label>' .
  230. '<input type="checkbox" name="c[6]" id="c6">' .
  231. '<label for="c6"></label>' .
  232. '<input type="checkbox" name="c[7]" id="c7">' .
  233. '<label for="c7"></label>' .
  234. '<input type="checkbox" name="c[8]" id="c8">' .
  235. '<label for="c8"></label>' .
  236. '<input type="checkbox" name="c[9]" id="c9">' .
  237. '<label for="c9"></label>' .
  238. '<input type="checkbox" name="c[10]" id="c10">' .
  239. '<label for="c10"></label>' .
  240. '<input type="checkbox" name="c[11]" id="c11">' .
  241. '<label for="c11"></label>' .
  242. '<input type="checkbox" name="c[12]" id="c12">' .
  243. '<label for="c12"></label>' .
  244. '<input type="checkbox" name="c[13]" id="c13">' .
  245. '<label for="c13"></label>' .
  246. '<input type="checkbox" name="c[14]" id="c14">' .
  247. '<label for="c14"></label>' .
  248. '<input type="checkbox" name="c[15]" id="c15">' .
  249. '<label for="c15"></label>' .
  250. '</div>' .
  251. '</div>' .
  252. '</div>' .
  253. '<input type="hidden" name="k" value="' . $key . '">' .
  254. '<input type="submit" value="Check IQ" class="captcha-submit">' .
  255. '</form>' .
  256. '</div>'
  257. ];
  258. http_response_code(429); // too many reqs
  259. $frontend->loadheader(
  260. $get,
  261. $filters,
  262. $page
  263. );
  264. echo $frontend->load("search.html", $payload);
  265. die();
  266. }
  267. }