Categories
PHP

Text file upload and search highlight utility with PHP

This was actually an assignment given to me as part of an interview process some time back.

The brief was simple: to have an upload utility that allowed a search term to be specified and a text file to be uploaded, with the contents of the uploaded file then displayed in the browser with the search term highlighted.

My first pass is a pure PHP solution. Please note this is not production code and I would never push code like this!

<?php

/*
 * - check the Execute Permissions of the upload directory
 * 
 * - checking file extensions in code using MIME type, which has some drawbacks as it is browser dependant
 * - added optional ability to restrict file type by extension (.txt) which is easy to extend to other file types - this is more restrictive & therefore more secure
 * - check size of uploaded file
 * - would normally move successfully uploaded file to another location (outside the web directory)
 *
 */

// max file upload size to be used in script
define('FILE_SIZE_LIMIT', 20480);

	if (isset($_POST['submit']))
	{
		// initialise an empty array to hold errors
		$errArr = array();
		
		// check to see if the user wants the search to be case sensitive or not
		$caseSensitive = (isset($_POST['casesensitive']) && $_POST['casesensitive'] == 'on')?'on':'off';
		
		// check to see if the user wants to allow only .txt files, or other text files as well
		$txtOnly = (isset($_POST['txtonly'])&&$_POST['txtonly']=='on')?'on':'off';	
		
		// check for and get the search term
		if(isset($_POST['searchterm']) && $_POST['searchterm'] != '')
		{
			$searchTerm = $_POST['searchterm'];
		}
		else
		{
			$errArr[] = 'You did not enter a search term';	
		}
			
		 // checks for errors and checks that file is uploaded
		if ($_FILES['uploadedfile']['error'] == UPLOAD_ERR_OK && is_uploaded_file($_FILES['uploadedfile']['tmp_name']))
		{
			// check the file type - this gets the MIME type - not neccessarily the best way to check, esp. for image files!!
			$fileType = $_FILES['uploadedfile']['type'];
			
			 // array will make it easier to add other files types later if we want to (csv,htm,html,xml,css,rtf etc)
			 $allowedExtensions = array("txt");
	
			// get the file extension
			$fileext = strtolower(substr(strrchr($_FILES['uploadedfile']['name'],'.'),1));
			
			// checking the MIME type
			if ($fileType == "text/plain")
			{
					
				// explicitely checking file extensions and creating a list of "allowed" extensions offers most control / security
				if($txtOnly == 'on' && !in_array($fileext, $allowedExtensions))
				{
					$errArr[] = "Files with that extension ($fileext) are not allowed!";
				}
				// get the file size
				$fileSize = $_FILES['uploadedfile']['size'];
				
				// check file size
				if($fileSize > 0)
				{
						
					if($fileSize <= FILE_SIZE_LIMIT)
					{
						// read the contents of the file
						$content = file_get_contents($_FILES['uploadedfile']['tmp_name']);
						
						// allow for line-breaks
						$content = str_replace("\n", "<br />", $content);
						
						// we need to have some checks in place on this uploaded content - this would be a start
						$content = htmlentities($content, ENT_QUOTES);
						
						// count number of times search term occurs in content
						// check to see if the user selected case-sensitive or not
						if($caseSensitive == 'on')
						{
							$searchCount = substr_count($content, $searchTerm);
							
							// output the contents of the file with the search term highlighted
							// below line is "first-pass" which obviously doesn't work with case-sensitive
							// would naturally replace it later with the final solution - leaving it in place for now...
							$output = str_replace($searchTerm, '<span class="highlighted-result">'.$searchTerm.'</span>', $content);

						}
						else
						{
							$searchCount = substr_count(strtolower($content), strtolower($searchTerm));
							
							// below is final solution to case sensitive problem when replacing / highlighting text
							// output the contents of the file with the search term highlighted
							$output = preg_replace("|($searchTerm)|Ui", "<span class=\"highlighted-result\">$1</span>", $content);
						}
						
						$output = html_entity_decode($output);
					}
					else
					{
						$errArr[] = 'That file is too big!';
					}
					
				}
				else
				{
					$errArr[] = 'That file is empty!';	
				}
				
				$fileName = $_FILES['uploadedfile']['name'];

			}
			else
			{
				$errArr[] = 'That is not a text file!';	
			}			 
		}
		else
		{
			$errArr[] = 'No file selected or there was an error uploading you file!';	
		}
	}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Text file upload and Highlight utility</title>
<link rel="stylesheet" href="stylee.css" type="text/css" />
</head>
<body>
<h1>Text file upload and Highlight utility</h1>
<?php
	
	if(isset($errArr)) // the array is set
	{
		if(empty($errArr)) // the array is empty - there were no errors - output the search results
		{
			// give info about the search term
			echo '<h2>Your search term <span class="highlighted-result">'.$searchTerm.'</span> occurred '.$searchCount.' times</h2>';
			echo '<p>Search info:</p>';
			echo '<ul><li>Name: '.$fileName.'</li><li>Size: '.$fileSize.'</li><li>Case sensitive:'.$caseSensitive.'</li></ul>';
			echo '<div id="output">'.$output.'</div>';	
		}
		else
		{
			foreach($errArr as $msg) // there were errors - output them
			{
				echo '<p class="error">'.$msg.'</p>';	
			}
		}
	}
	
?>

<ol>
	<li>Select a text file</li>
	<li>Enter a search term</li>
	<li>Submit to see results</li>
</ol>
<form enctype="multipart/form-data" action="index.php" method="post">
<fieldset>	
	<legend>Upload text file:</legend>
	<p><label for="uploadedfile">File:</label><input type="file" name="uploadedfile" /> (limit <?php echo FILE_SIZE_LIMIT; ?>)</p>
	<p><label for="searchterm">Search term:</label><input type="text" name="searchterm" id="searchterm" /></p>
	<p><input type="checkbox" name="casesensitive" /> Case sensitive</p>
	<p><input type="checkbox" name="txtonly" /> .txt extension only</p>
	<p><input name="submit" type="submit" value="submit" /></p>
</fieldset>	
</form>
</body>
</html>

See the demo here…

By foxbeefly

PHP / MySQL Developer

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.