<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Design Shack &#187; file</title>
	<atom:link href="http://designshack.net/tag/file/feed" rel="self" type="application/rss+xml" />
	<link>http://designshack.net</link>
	<description>Inspiration, CSS Gallery &#38; Community News</description>
	<lastBuildDate>Thu, 09 Feb 2012 06:00:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Smart File Type Detection Using PHP</title>
		<link>http://designshack.net/articles/php-articles/smart-file-type-detection-using-php/</link>
		<comments>http://designshack.net/articles/php-articles/smart-file-type-detection-using-php/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 08:59:51 +0000</pubDate>
		<dc:creator>Kishore Nallan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[detection]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.designshack.co.uk/?p=689</guid>
		<description><![CDATA[In most web applications today, there is a need to allow users to upload images, audio and video files. Sometimes, we also need to restrict certain types of files from being uploaded &#8211; an executable file being an obvious example. Security aside, one might also want to prevent users from misusing the upload facility, e.g. [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.designshack.net/wp-content/uploads/padlock.jpg" alt="padlock" title="padlock" width="200" height="200" class="right size-full wp-image-722" />In most web applications today, there is a need to allow  users to upload images, audio and video files. Sometimes, we also need to  restrict certain types of files from being uploaded &#8211; an executable file being an obvious example.</p>
<p>Security aside, one might also want to prevent users from misusing  the upload facility, e.g. uploading copyrighted music files illegally and using the service to promote piracy! In this article, we&#8217;ll look into a few ways in which we can achieve this.</p>
<p><span id="more-689"></span></p>
<h2>File  type detection using extension and MIME types</h2>
<p>I am not going to talk about this in too much detail as  after all, this is what we normally do when we want to restrict certain files.  We simply get the MIME type of the file using  <code>$_FILES['myFile']['type']</code> and check if it’s of a  valid type.</p>
<p>Or we might scan the last few characters of the file name  and reject files ending with a certain extension.  Unfortunately, these methods are hardly  sufficient, as one can easily change the extension of a file to bypass this  restriction. Furthermore, MIME type information is given by the browser and most browsers, if not all, determine the mime type based upon the  file&#8217;s extension! Hence MIME types can be pretty easily spoofed too.</p>
<p>Let&#8217;s now explore some others ways which offer better fool-proofness.</p>
<h2>Using Magic Bytes</h2>
<p>The best way to determine the file type is by examining the first few bytes of a file &#8211; referred to as &#8220;magic bytes&#8221;. Magic bytes are essentially signatures that vary in length between 2 to 40 bytes in the file headers, or at the end of a file. There are several hundred types of files, and quite a few of them have several file signatures associated with them. You can see a list of file signatures <a href="http://www.garykessler.net/library/file_sigs.html">over here</a>.</p>
<p>Although inconsistent, this is our best bet in detecting file types reliably. This seemingly difficult task has been made really easy by a PECL extension called <a href="http://pecl.php.net/package/Fileinfo">Fileinfo</a>. As of PHP 5.3, Fileinfo is shipped with the main distribution and is enabled by default, so this is definitely a robust and simple way to detect and impose restrictions on the types of files uploaded.</p>
<p>Let&#8217;s now see how we can detect a file type using Fileinfo:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$file</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;/path/to/file&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// in PHP 4, we can do:</span>
<span style="color: #000088;">$fhandle</span> <span style="color: #339933;">=</span> <span style="color: #990000;">finfo_open</span><span style="color: #009900;">&#40;</span>FILEINFO_MIME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$mime_type</span> <span style="color: #339933;">=</span> <span style="color: #990000;">finfo_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fhandle</span><span style="color: #339933;">,</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// e.g. gives &quot;image/jpeg&quot; </span>
&nbsp;
<span style="color: #666666; font-style: italic;">// in PHP 5, we can do:</span>
&nbsp;
<span style="color: #000088;">$file_info</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> finfo<span style="color: #009900;">&#40;</span>FILEINFO_MIME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">// object oriented approach!</span>
<span style="color: #000088;">$mime_type</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$file_info</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">buffer</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">// e.g. gives &quot;image/jpeg&quot;</span>
&nbsp;
<span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mime_type</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">case</span> <span style="color: #0000ff;">&quot;image/jpeg&quot;</span><span style="color: #339933;">:</span>
		<span style="color: #666666; font-style: italic;">// your actions go here...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2>Handling image uploads</h2>
<p>If you intend to allow only image uploads, then you can use  the inbuilt <code>getimagesize()</code> function to ensure that the user is actually uploading a valid image file. This functions returns false, if the file is not a valid image file.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//  Let's assume that the name attribute of the file input field you have used is &quot;myfile&quot;</span>
&nbsp;
<span style="color: #000088;">$tempFile</span> <span style="color: #339933;">=</span>  <span style="color: #000088;">$_FILES</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'myFile'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tmp_name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>  <span style="color: #666666; font-style: italic;">// path of the temp file created by PHP during upload</span>
<span style="color: #000088;">$imginfo_array</span> <span style="color: #339933;">=</span> <span style="color: #990000;">getimagesize</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tempFile</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>   <span style="color: #666666; font-style: italic;">// returns a false if not a valid image file</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$imginfo_array</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$mime_type</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$imginfo_array</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mime'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mime_type</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
&nbsp;
	<span style="color: #b1b100;">case</span> <span style="color: #0000ff;">&quot;image/jpeg&quot;</span><span style="color: #339933;">:</span>
		<span style="color: #666666; font-style: italic;">// your actions go here...</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;This is not a valid image file&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2>Reading and interpreting magic bytes manually</h2>
<p>If for some reason, you are not able to install Fileinfo, then you can still manually determine the file type by reading the first few bytes of a file and comparing them with known magic bytes associated with the particular file type. This process definitely has an element of trial and error, because there is still a chance that there are a few undocumented magic bytes associated with legitimate file formats. As a result, valid files could be rejected by your system. However it&#8217;s not impossible as a couple of years back, I was asked to work on a script that allowed only genuine mp3 files to be uploaded, and since we could not use Fileinfo, we resorted to this manual scanning. It took me a  while to account for some of the undocumented magic bytes for mp3, but pretty soon, I got a stable upload script running.</p>
<p>Before I end, I would just like to part with a general word of caution: Make sure that you never call an <code>include()</code> with a file that was uploaded, as PHP  code can very well be hidden as part of the picture, and the picture would pass your tests for file validation just fine, only to cause havoc when executed by the server.</p>
]]></content:encoded>
			<wfw:commentRss>http://designshack.net/articles/php-articles/smart-file-type-detection-using-php/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Object Caching 197/219 objects using disk: basic

Served from: designshack.net @ 2012-02-09 15:04:50 -->
