diff options
Diffstat (limited to 'lib/captcha_gen.php')
-rw-r--r-- | lib/captcha_gen.php | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/lib/captcha_gen.php b/lib/captcha_gen.php new file mode 100644 index 0000000..2ae824b --- /dev/null +++ b/lib/captcha_gen.php @@ -0,0 +1,325 @@ +<?php + +class captcha{ + + public function __construct($frontend, $get, $filters, $page, $output){ + + /* + Validate cookie, if it exists + */ + if(isset($_COOKIE["pass"])){ + + if( + // check if key is not malformed + preg_match( + '/^c[0-9]+\.[A-Za-z0-9]{20}$/', + $_COOKIE["pass"] + ) && + // does key exist + apcu_exists($_COOKIE["pass"]) + ){ + + // exists, increment counter + $inc = apcu_inc($_COOKIE["pass"]); + + // we start counting from 1 + // when it has been incremented to 102, it has reached + // 100 reqs + if($inc >= 102){ + + // reached limit, delete and give captcha + apcu_delete($_COOKIE["pass"]); + }else{ + + // the cookie is OK! dont die() and give results + if($output === true){ + $frontend->loadheader( + $get, + $filters, + $page + ); + } + return; + } + } + } + + if($output === false){ + + echo json_encode([ + "status" => "The \"pass\" token in your cookies is missing or has expired!!" + ]); + die(); + } + + /* + Validate form data + */ + $lines = + explode( + "\r\n", + file_get_contents("php://input") + ); + + $invalid = false; + $answers = []; + $key = false; + $error = ""; + + foreach($lines as $line){ + + $line = explode("=", $line, 2); + + if(count($line) !== 2){ + + $invalid = true; + break; + } + + preg_match( + '/^c\[([0-9]+)\]$/', + $line[0], + $regex + ); + + if( + $line[1] != "on" || + !isset($regex[0][1]) + ){ + + // check if its k + if( + $line[0] == "k" && + strpos($line[1], "c.") === 0 + ){ + + $key = apcu_fetch($line[1]); + apcu_delete($line[1]); + } + break; + } + + $regex = (int)$regex[1]; + + if( + $regex >= 16 || + $regex <= -1 + ){ + + $invalid = true; + break; + } + + $answers[] = $regex; + } + + if( + !$invalid && + $key !== false + ){ + $check = $key[1]; + + // validate answer + for($i=0; $i<count($key[0]); $i++){ + + if(!in_array($i, $answers)){ + + continue; + } + + if($key[0][$i][0] == $key[2]){ + + $check--; + }else{ + + // got a wrong answer + $check = -1; + break; + } + } + + if($check === 0){ + + // we passed the captcha + // set cookie + $inc = apcu_inc("cookie"); + $chars = + array_merge( + range("A", "Z"), + range("a", "z"), + range(0, 9) + ); + + $c = count($chars) - 1; + + $key = "c" . $inc . "."; + + for($i=0; $i<20; $i++){ + + $key .= $chars[random_int(0, $c)]; + } + + apcu_inc($key, 1, $stupid, 86400); + + setcookie( + "pass", + $key, + [ + "expires" => time() + 86400, // expires in 24 hours + "samesite" => "Strict", + "path" => "/" + ] + ); + + $frontend->loadheader( + $get, + $filters, + $page + ); + return; + + }else{ + + $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>"; + } + } + + /* + Generate random grid data to pass to captcha.php + */ + $dataset = [ + ["birds", 2263], + ["fumo_plushies", 1006], + ["minecraft", 848] + ]; + + // get the positions for the answers + // will return between 3 and 6 answer positions + $range = range(0, 15); + $answer_pos = []; + + array_splice($range, 0, 1); + + for($i=0; $i<random_int(3, 6); $i++){ + + $answer_pos_tmp = + array_splice( + $range, + random_int( + 0, + 14 - $i + ), + 1 + ); + + $answer_pos[] = $answer_pos_tmp[0]; + } + + // choose a dataset + $choosen = &$dataset[random_int(0, count($dataset) - 1)]; + $choices = []; + + for($i=0; $i<count($dataset); $i++){ + + if($dataset[$i][0] == $choosen[0]){ + + continue; + } + + $choices[] = $dataset[$i]; + } + + // generate grid data + $grid = []; + + for($i=0; $i<16; $i++){ + + if(in_array($i, $answer_pos)){ + + $grid[] = $choosen; + }else{ + + $grid[] = $choices[random_int(0, count($choices) - 1)]; + } + } + + $key = "c." . apcu_inc("captcha_gen", 1) . "." . random_int(0, 100000000); + + apcu_store( + $key, + [ + $grid, + count($answer_pos), + $choosen[0], + false // has captcha been generated? + ], + 120 // we give user 2 minutes to get captcha, in case of network error + ); + + $payload = [ + "class" => "", + "right-left" => "", + "right-right" => "", + "left" => + '<div class="infobox">' . + '<h1>IQ test</h1>' . + 'Due to getting hit with 20,000 bot requests per day, I had to put this up. Sorry.<br><br>' . + '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!!' . + $error . + '<form method="POST" enctype="text/plain" autocomplete="off">' . + '<div class="captcha-wrapper">' . + '<div class="captcha">' . + '<img src="captcha.php?k=' . $key . '" alt="Captcha image">' . + '<div class="captcha-controls">' . + '<input type="checkbox" name="c[0]" id="c0">' . + '<label for="c0"></label>' . + '<input type="checkbox" name="c[1]" id="c1">' . + '<label for="c1"></label>' . + '<input type="checkbox" name="c[2]" id="c2">' . + '<label for="c2"></label>' . + '<input type="checkbox" name="c[3]" id="c3">' . + '<label for="c3"></label>' . + '<input type="checkbox" name="c[4]" id="c4">' . + '<label for="c4"></label>' . + '<input type="checkbox" name="c[5]" id="c5">' . + '<label for="c5"></label>' . + '<input type="checkbox" name="c[6]" id="c6">' . + '<label for="c6"></label>' . + '<input type="checkbox" name="c[7]" id="c7">' . + '<label for="c7"></label>' . + '<input type="checkbox" name="c[8]" id="c8">' . + '<label for="c8"></label>' . + '<input type="checkbox" name="c[9]" id="c9">' . + '<label for="c9"></label>' . + '<input type="checkbox" name="c[10]" id="c10">' . + '<label for="c10"></label>' . + '<input type="checkbox" name="c[11]" id="c11">' . + '<label for="c11"></label>' . + '<input type="checkbox" name="c[12]" id="c12">' . + '<label for="c12"></label>' . + '<input type="checkbox" name="c[13]" id="c13">' . + '<label for="c13"></label>' . + '<input type="checkbox" name="c[14]" id="c14">' . + '<label for="c14"></label>' . + '<input type="checkbox" name="c[15]" id="c15">' . + '<label for="c15"></label>' . + '</div>' . + '</div>' . + '</div>' . + '<input type="hidden" name="k" value="' . $key . '">' . + '<input type="submit" value="Check IQ" class="captcha-submit">' . + '</form>' . + '</div>' + ]; + + http_response_code(429); // too many reqs + $frontend->loadheader( + $get, + $filters, + "web" + ); + + echo $frontend->load("search.html", $payload); + die(); + } +} |