forked from lolcat/4get
		
	
		
			
				
	
	
		
			337 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			337 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| class captcha{
 | |
| 	
 | |
| 	public function __construct($frontend, $get, $filters, $page, $output){
 | |
| 		
 | |
| 		// check if we want captcha
 | |
| 		if(config::BOT_PROTECTION !== 1){
 | |
| 			
 | |
| 			apcu_inc("real_requests");
 | |
| 			if($output === true){
 | |
| 				$frontend->loadheader(
 | |
| 					$get,
 | |
| 					$filters,
 | |
| 					$page
 | |
| 				);
 | |
| 			}
 | |
| 			return;
 | |
| 		}
 | |
| 		
 | |
| 		/*
 | |
| 			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
 | |
| 					apcu_inc("real_requests");
 | |
| 					
 | |
| 					if($output === true){
 | |
| 						$frontend->loadheader(
 | |
| 							$get,
 | |
| 							$filters,
 | |
| 							$page
 | |
| 						);
 | |
| 					}
 | |
| 					return;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		
 | |
| 		if($output === false){
 | |
| 			
 | |
| 			http_response_code(429); // too many reqs
 | |
| 			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);
 | |
| 				
 | |
| 				apcu_inc("real_requests");
 | |
| 				
 | |
| 				setcookie(
 | |
| 					"pass",
 | |
| 					$key,
 | |
| 					[
 | |
| 						"expires" => time() + 86400, // expires in 24 hours
 | |
| 						"samesite" => "Lax",
 | |
| 						"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>";
 | |
| 			}
 | |
| 		}
 | |
| 		
 | |
| 		// 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
 | |
| 		$c = count(config::CAPTCHA_DATASET);
 | |
| 		$choosen = config::CAPTCHA_DATASET[random_int(0, $c - 1)];
 | |
| 		$choices = [];
 | |
| 
 | |
| 		for($i=0; $i<$c; $i++){
 | |
| 			
 | |
| 			if(config::CAPTCHA_DATASET[$i][0] == $choosen[0]){
 | |
| 				
 | |
| 				continue;
 | |
| 			}
 | |
| 			
 | |
| 			$choices[] = config::CAPTCHA_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?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,
 | |
| 			$page
 | |
| 		);
 | |
| 		
 | |
| 		echo $frontend->load("search.html", $payload);
 | |
| 		die();
 | |
| 	}
 | |
| }
 |