//always use constants when making file paths, to avoid the possibilty of remote file inclusion

//always use constants when making file paths, to avoid the possibilty of remote file inclusion

Line 289:

Line 289:

5) This could be considered a security issue but probably not severe enough to actually compromise any data. The cookies created in IE by Flash still have all the rules and restricts associated with cookies in any browser.

5) This could be considered a security issue but probably not severe enough to actually compromise any data. The cookies created in IE by Flash still have all the rules and restricts associated with cookies in any browser.

Part 1: Introduction

The standard way to upload a file is with a HTML form. This works great if you are uploading one file, but browsers do not let you select and upload more than one file at a time (Update Feb 2010, Firefox 3.5+ and some other modern browsers support the HTML5 multiple file input)

The most common way of selecting multiple files for upload is to use flash and javascript. The flash part of the script opens up a select file dialog where multiple files can be selected, and the flash/javascript sends each file, and receives the response from the server.

The most popular scripts used to do this are SWFUpload and Fancy upload (http://digitarald.de/project/fancyupload/). The flash uploader in Joomla's media manager is based on Fancy Upload version 1.0. As Fancy upload 2.0 and 3.0 use mootools 1.2, and Joomla 1.5 uses mootools 1.11, we can not use Fancy Upload 2.0/3.0 in the admin pages of Joomla. Fancy Upload 1.0 could be used, but it is not updated or supported anymore.

SWFUpload does not use Mootools or Jquery. Because of this it will likely work on any page with Mootools 1.11 (Joomla 1.5), or Mootools 1.2 (Joomla 1.6). Therefore we will be using SWFUpload in this article.

Part 2: Adding The External Javascript

We need to add in the external links in the head of the document, put some javascript into the head of the doc, and put some HTML in our body.

If you look at the simpledemo/index.php page you will see links to 5 files in the head of the page.

Make a folder within the root of your components folder called swfupload, copy the ../css/default.css, ../swfupload/swfupload.js, js/swfupload.queue.js, js/fileprogress.js and js/handlers.js files into this folder.

We also need to copy the ../swfupload/swfupload.swf and images/TestImageNoText_65x29.png files into this folder.

Within your view.html.php file add in the following code:

//get the hosts name
jimport('joomla.environment.uri');$host= JURI::root();//add the links to the external files into the head of the webpage (note the 'administrator' in the path, which is not nescessary if you are in the frontend)$document=& JFactory::getDocument();$document->addScript($host.'administrator/components/com_mycomponent/swfupload/swfupload.js');$document->addScript($host.'administrator/components/com_mycomponent/swfupload/swfupload.queue.js');$document->addScript($host.'administrator/components/com_mycomponent/swfupload/fileprogress.js');$document->addScript($host.'administrator/components/com_mycomponent/swfupload/handlers.js');$document->addStyleSheet($host.'administrator/components/com_mycomponent/swfupload/default.css');

That is the external files part done. We still have to add in the head javascript, and the body html.

Part 3: Adding The Head Javascript

Head javascript part: The javascript below is almost the same as the javascript from the simple demo, the few modifications are commented. It is nescessary to read through it and change the parts (such as task) that are relevant to your component.

If all has gone well, you will be able to upload files to your components script, although nothing will happen on the server as there is no PHP to receive the image.

Part 5: Receiving The File With PHP

It is worth noting that allowing users to upload files to the server is possibly the most dangerous thing to do in terms of security, and if someone with malicious intentions manages to upload a php file to your server, then they can easily take control of the site.

It is recommended you do some reading on file upload security. This is a good start:

And there are many other good resources on the internet. It is important you understand how file upload security works, rather than copying and pasting some code that checks the MIME type, and assuming the script is safe.

Here is some example PHP that will check if the file is an image, and upload it. It is not an exhaustive example of security checking, but it is a good start:

//import joomlas filesystem functions, we will do all the filewriting with joomlas functions,//so if the ftp layer is on, joomla will write with that, not the apache user, which might//not have the correct permissions
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');//this is the name of the field in the html form, filedata is the default name for swfupload//so we will leave it as that$fieldName='Filedata';//any errors the server registered on uploading$fileError=$_FILES[$fieldName]['error'];if($fileError>0){switch($fileError){case1:echo JText::_('FILE TO LARGE THAN PHP INI ALLOWS');return;case2:echo JText::_('FILE TO LARGE THAN HTML FORM ALLOWS');return;case3:echo JText::_('ERROR PARTIAL UPLOAD');return;case4:echo JText::_('ERROR NO FILE');return;}}//check for filesize$fileSize=$_FILES[$fieldName]['size'];if($fileSize>2000000){echo JText::_('FILE BIGGER THAN 2MB');}//check the file extension is ok$fileName=$_FILES[$fieldName]['name'];$uploadedFileNameParts=explode('.',$fileName);$uploadedFileExtension=array_pop($uploadedFileNameParts);$validFileExts=explode(',','jpeg,jpg,png,gif');//assume the extension is false until we know its ok$extOk=false;//go through every ok extension, if the ok extension matches the file extension (case insensitive)//then the file extension is okforeach($validFileExtsas$key=>$value){if(preg_match("/$value/i",$uploadedFileExtension)){$extOk=true;}}if($extOk==false){echo JText::_('INVALID EXTENSION');return;}//the name of the file in PHP's temp directory that we are going to move to our folder$fileTemp=$_FILES[$fieldName]['tmp_name'];//for security purposes, we will also do a getimagesize on the temp file (before we have moved it //to the folder) to check the MIME type of the file, and whether it has a width and height$imageinfo=getimagesize($fileTemp);//we are going to define what file extensions/MIMEs are ok, and only let these ones in (whitelisting), rather than try to scan for bad//types, where we might miss one (whitelisting is always better than blacklisting) $okMIMETypes='image/jpeg,image/pjpeg,image/png,image/x-png,image/gif';$validFileTypes=explode(",",$okMIMETypes);//if the temp file does not have a width or a height, or it has a non ok MIME, returnif(!is_int($imageinfo[0])||!is_int($imageinfo[1])||!in_array($imageinfo['mime'],$validFileTypes)){echo JText::_('INVALID FILETYPE');return;}//lose any special characters in the filename$fileName=preg_replace("/[^A-Za-z0-9]/i","-",$fileName);//always use constants when making file paths, to avoid the possibilty of remote file inclusion$uploadPath= JPATH_SITE.DS.'images'.DS.'stories'.DS.$fileName;if(!JFile::upload($fileTemp,$uploadPath)){echo JText::_('ERROR MOVING FILE');return;}else{// success, exit with code 0 for Mac users, otherwise they receive an IO Errorexit(0);}

If all want well the uploaded files will be in the images/stories folder.

Part 6: Flash plugin COOKIE bug on non-IE browsers

The Flash Player Plugin for FireFox, Opera and Safari (and probably other non-IE based browsers) has a bug which sends persistent cookies from IE to the upload URL instead of the cookies from the browser. Session only cookies from IE are not sent.

1) Any cookies from a non-IE browser (ie, authentication, login, etc) will not be sent with the file upload. Rather the cookies from IE will be sent. So, no cookies or the wrong cookies will be sent. In most cases this means sessions and cookie based authentication are lost when making an upload.

2) Cookies set by the upload script do get set, but only for Flash. The browser will not see them.

3) This bug affects Flash 8 and Flash 9 and all versions of SWFUpload

4) You cannot rely on cookies when using SWFUpload (or any Flash based upload tool). You must send the data you need from the cookies in another way. There are several threads regarding this issue in the forum and many of the demos show workarounds for restoring PHP sessions and some sample files show how to restore the cookies so Session and Authentication are restored in ASP.Net.

5) This could be considered a security issue but probably not severe enough to actually compromise any data. The cookies created in IE by Flash still have all the rules and restricts associated with cookies in any browser.