<?php    
session_start();

if (isset($_COOKIE['ws']) && htmlspecialchars($_COOKIE['ws']) == "0")
{
	$worksafe = false;
}else{
	$worksafe = true;
}
if (isset($_COOKIE['hs']) && htmlspecialchars($_COOKIE['hs']) == "1")
{
	$filterHTTPS = true;
}else{
	$filterHTTPS = false;
}

if (!isset($_REQUEST['q']))    
{    
  include 'form.html.php';    
}  

else
{    
	$link = mysqli_connect('localhost', 'guest', 'qwer');
			
	$query = mysqli_real_escape_string($link, $_GET['q']);

	$lim = 12;

	$starappend = 0;

	$startID = 0;
	
	if(isset($_REQUEST['nsfw']))
	{
		$worksafe = false;
	}

	$page=0;
	if (!isset($_REQUEST['p'])) 
	{
		$offset=0;
	}
	else
	{
		$page = mysqli_real_escape_string($link, $_GET['p']);
		$offset = $page;
		if($offset > 0)
		{
			$offset--;
		}
		$offset = $offset * $lim;
	}

	//check if doing a more general search
	$general=false;
	if (isset($_REQUEST['g']))    
	{    
	  $general=true;   
	} 
	
	if (!$link)
	{
		$error = 'Cant connect to database.';
		include 'error.html.php';
		exit();
	}

	if (!mysqli_set_charset($link, 'utf8mb4'))
	{ 
	  $error = 'Unable to set database connection encoding.'; 
	  include 'error.html.php'; 
	  exit(); 
	}
	
	if(!mysqli_select_db($link, 'wiby'))
	{
	  $error = 'Unable to locate the database.'; 
	  include 'error.html.php'; 
	  exit(); 
	}
	
	//Check if query is a url (contains http:// or https:// and no spaces). If so, put quotations around to to get an exact match
	$urlDetected = 0;
	if(strpos($query, ' ') == false && strpos($query,'.') == true && strpos($query,'"') == false && preg_match('/http/',$query) == true)
	{
		$queryOriginal = $query;
		$query = '"' . $query . '"';
		$urlDetected = 1;
	}

	//did user manually set -https instead of settings cookie?
	if(substr($query,-7) == " -https"){
		$filterHTTPS = true;
		$query = substr($query, 0,-7);	
	}
	$queryNoQuotes = $query;
	
	//if query is just 1 or 2 letters, help make it work. Also CIA :D
	if(strlen($query) < 3 || $query == "cia" || $query == "CIA"){
		$query = " ".$query." *";
	}
	if($query == "c++" || $query == "C++"){//shitty but works
		$query = "c++ programming";
	}

	$queryNoQuotes = $query;	

	//Are there quotes in the query?
	$exactMatch = false;
	if(strpos($queryNoQuotes,'"') !== false)
	{
		$exactMatch = true;
	}
	
	//alright then lets remove the quotes
	if($exactMatch == true)
	{
		while(strpos($queryNoQuotes,'"') !== false)
		{
			$queryNoQuotes = str_replace('"', "",$queryNoQuotes);
		}
	}

	//first remove any flags inside queryNoQuotes, also grab any required words (+ prefix) 
	$queryNoQuotesOrFlags = '';
	$requiredword = '';
	$flags = '';
	if(strpos($queryNoQuotes,'+') !== false || strpos($queryNoQuotes,'-') !== false){
		$words = explode(' ', $queryNoQuotes);	
		$i = 0;
		foreach ($words as $word) {
			if($i != 0 && $word[0] != '-' && $word[0] != '+'){
				$queryNoQuotesOrFlags .= ' ';
			}			
			if ($word[0] != '-' && $word[0] != '+'){
				$queryNoQuotesOrFlags .= $word;
			}
			if ($word[0] == '+' && strlen($word) > 1){
				$requiredword = substr($word,1);
			}
			if ($word[0] == '-' && $word[0] == '+'){
				$flags .= " $word";
			}			
			$i++;
		}
	}

	//remove the '*' if contained anywhere in queryNoQuotes
	if(strpos($queryNoQuotes,'*') !== false && $exactMatch == false){
		$queryNoQuotes = str_replace('*', "",$queryNoQuotes);
	}

	$queryNoQuotes_SQLsafe = mysqli_real_escape_string($link, $queryNoQuotes);
	$flags = mysqli_real_escape_string($link, $flags);

	if($exactMatch == false)
	{
		//find longest word in query 	
		$words  = explode(' ', $queryNoQuotes);
		$longestWordLength = 0;
		$longestWord = '';
		$wordcount = 0;
		$longestwordelementnum = 0;
		foreach ($words as $word) {
		   if (strlen($word) > $longestWordLength) {
		      $longestWordLength = strlen($word);
		      $longestWord = $word;
		      $longestwordelementnum = $wordcount;
		   }
		   $wordcount++;
		}
	}

	$additions = '';
	if($filterHTTPS == true){
		$additions = $additions."AND http = '1' ";
	}
	if($worksafe == true){
		$additions = $additions."AND worksafe = '1' ";
	}

	$count = 0;
	
	if(!$general){
		$queryWithQuotesAndFlags = '"'. $queryNoQuotes_SQLsafe.'"'.$flags.'';

		//perform full text search FOR InnoDB or MyISAM STORAGE ENGINE
		$outputFTS = mysqli_query($link, "SELECT id, url, title, description, body FROM windex WHERE Match(tags, body, description, title, url) Against('$queryWithQuotesAndFlags' IN BOOLEAN MODE) AND enable = '1' $additions ORDER BY CASE WHEN LOCATE('$queryNoQuotes_SQLsafe', tags)>0 THEN 30 WHEN LOCATE('$queryNoQuotes_SQLsafe', title)>0 AND Match(title) AGAINST('$queryWithQuotesAndFlags' IN BOOLEAN MODE) THEN 20 WHEN LOCATE('$queryNoQuotes_SQLsafe', title)>0 THEN 16 WHEN Match(title) AGAINST('$queryWithQuotesAndFlags' IN BOOLEAN MODE) THEN Match(title) AGAINST('$queryWithQuotesAndFlags' IN BOOLEAN MODE) END DESC, id DESC LIMIT $lim OFFSET $offset");

		/*if(!$outputFTS)//dont error out yet, will give another try below
		{
		  $error = 'Error ' . mysqli_error($link);  
		  include 'error.html.php';  
		  exit(); 
		}*/
		
		if($urlDetected == 1)
		{
			$query = $queryOriginal;
		}

		//this will get set if position of longest word of query is found within body
		$pos = -1;

		//lets put contents of the full text search into the array
		while($row = mysqli_fetch_array($outputFTS))
		{
			//put the contents of the URL column within the DB into an array
			$id[] = $row[0];
			$url[] = $row[1];
			$title[] = substr($row[2],0,150);
			$description[] = substr($row[3],0,180);
			$body = $row[4];
			$count++;
			$lastID = $row[0];
			
			if($exactMatch == false)
			{
				//remove the '*' at the end of the longest word if present
				if(strpos($longestWord,'*') == true)
				{
					$longestWord = str_replace('*', "",$longestWord);
				}

				//first find an exact
				if(strlen($requiredword) > 0){
					$pos = stripos($body, $requiredword);			
				}else{
					$pos = stripos($body, $queryNoQuotes);
				}
		
				//search within body for position of longest query word. If not found, try another word	
				if($pos == false){	
					$pos = stripos($body, $longestWord);
					if($pos == false && $wordcount > 1)
					{
						if($longestwordelementnum > 0)
						{
							if(strpos($words[0],'*') == true)//remove the '*' at the end of the query if present
								$words[0] = str_replace('*', "",$words[0]);					
							$pos = stripos($body, $words[0]);
						}
						else if($longestwordelementnum == 0)
						{
							if(strpos($words[1],'*') == true)//remove the '*' at the end of the query if present
								$words[1] = str_replace('*', "",$words[1]);				
							$pos = stripos($body, $words[1]);
						}		
					}
				}
			}
			else
			{
				$pos = stripos($body, $queryNoQuotes);
			}
			//still not found?, set position to 0
			if($pos == false){
				$pos = 0;
			}

			//get all positions of all keywords in body
		/*	$lastPos = 0;
			$positions = array();
			foreach($words as $word)
			{
				while (($lastPos = mb_strpos($body, $word, $lastPos))!== false) {
					$positions[$word][] = $lastPos;
					$lastPos = $lastPos + strlen($word);
				}		
			}*/
			
			//figure out how much preceding text to use	
			if($pos < 32)		
				$starttext = 0;
			else if($pos > 25)		
				$starttext = $pos - 25;
			else if($pos > 20)
				$starttext = $pos - 15;
			//else $starttext = 0;

			//total length of the ballpark
			$textlength = 180;

			//populate the ballpark
			if($pos >= 0)
			{
				$ballparktext = substr($body,$starttext,$textlength);
			}
			else $ballpark = '0';
			
			//find position of nearest Period
				$foundPeriod = true;
			$posPeriod = stripos($ballparktext, '. ') + $starttext +1;

			//find position of nearest Space
				$foundSpace = true;
			$posSpace = stripos($ballparktext, ' ') + $starttext;
			
			//if longest word in query is after a period+space within ballpark, reset $starttext to that point 
			if($pos-$starttext > $posPeriod)
			{
				$starttext = $posPeriod;
				//populate the bodymatch
				if($pos-$starttext >= 0)
				{
					$bodymatch[] = substr($body,$starttext,$textlength);
				}
				else $bodymatch[] = '';
			}
			//else if($pos-starttext > $posSpace)//else if longest word in query is after a space within ballpark, reset $starttext to that point
			else if($pos > $posSpace)//else if longest word in query is after a space within ballpark, reset $starttext to that point
			{
				$starttext = $posSpace;
				//populate the bodymatch
				if($pos-$starttext >= 0)
				{
					$bodymatch[] = substr($body,$starttext,$textlength);
				}
				else $bodymatch[] = '';
			}
			else //else just set the bodymatch to the ballparktext
			{
				//populate the bodymatch
				if($pos-$starttext >= 0)
				{
					$bodymatch[] = $ballparktext;
				}
				else $bodymatch[] = '';	
			}
		
		}
	}
	$outputFTSrows=$count;
	//do a general search if exact results peter off
	if($outputFTSrows < 8 && $exactMatch == false){
		$count = 0;
		$general = true;

		//Check if query contains a hyphenated word. MySQL is finicky about them. We will wrap quotes around hyphenated words that aren't part of a string which is already wraped in quotes.
		if((strpos($queryNoQuotes,'-') !== false || strpos($queryNoQuotes,'+') !== false) && $urlDetected == false){
			$hyphenwords = explode(' ',$query);
			$query = '';
			$quotes = 0;
			$i = 0;
			foreach ($hyphenwords as $word) {
				if(strpos($queryNoQuotes,'"') !== false){
					$quotes++;
				}
				if(((strpos($queryNoQuotes,'-') !== false && $word[0] != '-') || (strpos($queryNoQuotes,'+') !== false && $word[0] != '+')) && $quotes%2 == 0){//if hyphen exists, not a flag, not wrapped in quotes already
					$word = '"' . $word . '"';
				}
				if($i > 0){
					$query .= ' ';
				}
				$query .= $word;
				$i++;
			}	
		}

		//perform full text search FOR InnoDB or MyISAM STORAGE ENGINE
		$outputFTSgeneral = mysqli_query($link, "SELECT id, url, title, description, body FROM windex WHERE Match(tags, body, description, title, url) Against('$query' IN BOOLEAN MODE) AND enable = '1' $additions ORDER BY CASE WHEN LOCATE('$queryNoQuotes_SQLsafe', tags)>0 THEN 30 WHEN LOCATE('$queryNoQuotes_SQLsafe', title)>0 AND Match(title) AGAINST('$query' IN BOOLEAN MODE) THEN 20 WHEN LOCATE('$queryNoQuotes_SQLsafe', title)>0 THEN 16 WHEN Match(title) AGAINST('$query' IN BOOLEAN MODE) THEN Match(title) AGAINST('$query' IN BOOLEAN MODE) END DESC, id DESC LIMIT $lim OFFSET $offset");


		//if all else fails, try a full text search with * appended (better to get something than nothing I suppose)
		if(mysqli_num_rows($outputFTSgeneral) == 0 && $offset == 0 && $urlDetected == 0)
		{
			$starappend = 1;
			$querystar = $query;
			//innodb will get fussy over some things if put in like '''' or ****, uncomment below lines if using innoDB
			$querystar = str_replace('*', "",$querystar);
			$querystar = str_replace('"', "",$querystar);
			$querystar = str_replace('"', "",$querystar);
			$querystar = str_replace('\'', "",$querystar);
			//-----------------------------------------------
		
			$querystar = $querystar . '*';

			//perform full text search FOR InnoDB or MyISAM STORAGE ENGINE
			$outputFTSgeneral = mysqli_query($link, "SELECT id, url, title, description, body FROM windex WHERE Match(tags, body, description, title, url) Against('$querystar' IN BOOLEAN MODE) AND enable = '1' $additions ORDER BY CASE WHEN LOCATE('$queryNoQuotes_SQLsafe', tags)>0 THEN 30 WHEN LOCATE('$queryNoQuotes_SQLsafe', title)>0 AND Match(title) AGAINST('$querystar' IN BOOLEAN MODE) THEN 20 WHEN LOCATE('$queryNoQuotes_SQLsafe', title)>0 THEN 16 WHEN Match(title) AGAINST('$querystar' IN BOOLEAN MODE) THEN Match(title) AGAINST('$querystar' IN BOOLEAN MODE) END DESC, id DESC LIMIT $lim OFFSET $offset");

			if(!$outputFTSgeneral)
			{
			  $error = 'Error ' . mysqli_error($link);  
			  include 'error.html.php';  
			  exit(); 
			}		
		}

		//this will get set if position of longest word of query is found within body
		$pos = -1;

		//lets put contents of the full text search into the array
		while($row = mysqli_fetch_array($outputFTSgeneral))
		{
			$count++;
			//check for duplicates if appending general search matches on the same page where exact matches were found
			$duplicate = false;
			if($outputFTSrows < 8 && $outputFTSrows > 0){
				foreach($id as $idtocheck){
					if($idtocheck==$row[0]){
						$duplicate=true;
						break;
					}

				}
			}
			if($duplicate==false){
				//put the contents of the URL column within the DB into an array
				$id[] = $row[0];
				$url[] = $row[1];
				$title[] = substr($row[2],0,150);
				$description[] = substr($row[3],0,180);
				$body = $row[4];
				$lastID = $row[0];
				if($exactMatch == false)
				{
					//remove the '*' at the end of the longest word if present
					if(strpos($longestWord,'*') == true)
					{
						$longestWord = str_replace('*', "",$longestWord);
					}

					//first find an exact
					if(strlen($requiredword) > 0){
						$pos = stripos($body, $requiredword);			
					}else{
						$pos = stripos($body, $queryNoQuotes);
					}
	
					//search within body for position of longest query word. If not found, try another word	
					if($pos == false){	
						$pos = stripos($body, $longestWord);
						if($pos == false && $wordcount > 1)
						{
							if($longestwordelementnum > 0)
							{
								if(strpos($words[0],'*') == true)//remove the '*' at the end of the query if present
									$words[0] = str_replace('*', "",$words[0]);					
								$pos = stripos($body, $words[0]);
							}
							else if($longestwordelementnum == 0)
							{
								if(strpos($words[1],'*') == true)//remove the '*' at the end of the query if present
									$words[1] = str_replace('*', "",$words[1]);				
								$pos = stripos($body, $words[1]);
							}		
						}
					}
				}
				else
				{
					$pos = stripos($body, $queryNoQuotes);
				}
				//still not found?, set position to 0
				if($pos == false){
					$pos = 0;
				}

				//get all positions of all keywords in body
			/*	$lastPos = 0;
				$positions = array();
				foreach($words as $word)
				{
					while (($lastPos = mb_strpos($body, $word, $lastPos))!== false) {
					    $positions[$word][] = $lastPos;
					    $lastPos = $lastPos + strlen($word);
					}		
				}*/
		
				//figure out how much preceding text to use	
				if($pos < 32)		
					$starttext = 0;
				else if($pos > 25)		
					$starttext = $pos - 25;
				else if($pos > 20)
					$starttext = $pos - 15;
				//else $starttext = 0;

				//total length of the ballpark
				$textlength = 180;

				//populate the ballpark
				if($pos >= 0)
				{
					$ballparktext = substr($body,$starttext,$textlength);
				}
				else $ballpark = '0';
		
				//find position of nearest Period
					$foundPeriod = true;
				$posPeriod = stripos($ballparktext, '. ') + $starttext +1;

				//find position of nearest Space
					$foundSpace = true;
				$posSpace = stripos($ballparktext, ' ') + $starttext;
		
				//if longest word in query is after a period+space within ballpark, reset $starttext to that point 
				if($pos-$starttext > $posPeriod)
				{
					$starttext = $posPeriod;
					//populate the bodymatch
					if($pos-$starttext >= 0)
					{
						$bodymatch[] = substr($body,$starttext,$textlength);
					}
					else $bodymatch[] = '';
				}
				//else if($pos-starttext > $posSpace)//else if longest word in query is after a space within ballpark, reset $starttext to that point
				else if($pos > $posSpace)//else if longest word in query is after a space within ballpark, reset $starttext to that point
				{
					$starttext = $posSpace;
					//populate the bodymatch
					if($pos-$starttext >= 0)
					{
						$bodymatch[] = substr($body,$starttext,$textlength);
					}
					else $bodymatch[] = '';
				}
				else //else just set the bodymatch to the ballparktext
				{
					//populate the bodymatch
					if($pos-$starttext >= 0)
					{
						$bodymatch[] = $ballparktext;
					}
					else $bodymatch[] = '';	
				}
			}
	
		}
	}

	$row = null;

        include 'results.json.php';    
}    

function JSONRealEscapeString($var){
	$var = str_replace("\\","\\\\",$var);
	$var = str_replace("\t","\\t",$var);
	$var = str_replace("\b","\\b",$var);
	$var = str_replace("\n","\\n",$var);
	$var = str_replace("\r","\\r",$var);
	$var = str_replace("\f","\\f",$var);
	return $var;
}

?>
