July 30, 2010, 10:31:20 am *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: Dont forget to check the Facile Forms wiki !
 
   Home   Help Search Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: Tutorial for a secure file upload and mail this as attachment.  (Read 5518 times)
Bonvie
Newbie

Offline Offline

Posts: 22


« on: January 05, 2008, 03:07:34 pm »

Hi all,
after a long time searching for details on www.facileforms.biz/forum with no success, I decided to work hard on this upload stuff and write then this tutorial, hope this helps.

First of all FacileForms is NOT unsecure, but you are able to build up unsecure upload forms. So please be aware that all checks that you do in the element form are based on javascript and so are running in a not trustable environment.
In the upload element Form you are able to define the maxlength and the accepted file types. FacileForms generates with this parameter the following html code:
Code:
<input ..... maxlength="1000000" accept="text/plain,application/zip" ..... class="inputbox"/>

So the implementation of FacileForms is alright but the browsers do not use these parameters.
You can find this for example here: http://htmlhelp.com/reference/html40/forms/input.html
"….While the MAXLENGTH attribute can be an effective guide to the user, authors should not depend on the enforcement of a maximum number of characters by the client. A user could copy the HTML document, remove the MAXLENGTH attribute, and submit the form. Thus authors of form handlers should ensure that any necessary input length checks are repeated on the server side….."
"….The ACCEPT attribute gives a comma-separated list of media types accepted, allowing the browser to filter out inappropriate files. Current browsers generally ignore the ACCEPT attribute…."


So what can we do when these parameters don't work? We can use javascript to direct the users, not really control :-)
As javascript is not allowed to access the local file system (thanks god), we are not able to manage the filesize but we can check the file type depending on the filename. So let's check the allowed file extensions. Place the following code in the validation script of your upload element and change the name of the function depending on the name of your element.
Code:
function ff_cf_fileupload_validation(element, message)
{
    if(element.value != '')
    {
        exts_string = 'txt,zip';

        exts = exts_string.split(',');
        ext = element.value.substring(element.value.length-3,element.value.length);
        ext = ext.toLowerCase();

        for(p=0;p<exts.length;p++) {
            if (ext == exts[p])
              return '';
        }

        if (message=='') message = 'The .' + ext + ' is an invalid file type!\n'
        ff_validationFocus(element.name);
        return message;
    }
    return '';
} // ff_cf_fileupload_validation

That's all that we can do on the client side and I can't follow up it enough, this is no security it is just to direct the normal user.

So let's see what we can secure on the server side, our trusted environment. Because we are on the server side we switch now the language to PHP (so no javascript). As I hade a little trouble with my webside provider I describe first how you can check your PHP installation and you possibilities.
Transmit some files you want to accept in future and create a PHP file on you side with the following code. Play a little bit with functions and try to check those files. For me are txt and zip files (later rtf) currently allowed:
Code:
<HTML>
<HEAD></HEAD>
<BODY>
<?php

$filename1 
"/var/www/html/cms/Test.txt";
echo 
mime_content_type($filename1)."<BR>";

$filename2 "/var/www/html/cms/Test.rtf";
echo 
mime_content_type($filename2)."<BR>";

$filename3 "/var/www/html/cms/Test.zip";
echo 
mime_content_type($filename3)."<BR>";

echo 
"<BR><BR><BR>";

//  application/zip
//  application/x-zip
//  text/plain
//  text/rtf

// $ft = mime_content_type ($image);
// with 
// $finfo = finfo_open (FILEINFO_MIME);
// $ft = finfo_file ($finfo, $image);
// finfo_close ($finfo);
// both return "image/gif"

switch (mime_content_type($filename1)) {
case 'application/zip':
case 'application/x-zip':
case 'text/plain':  
case 'text/rtf':  
echo "YES <BR>"
break; 
default: 
echo "NO <BR>"
break;
}

?>

</BODY>
</HTML>

Use your browser to access this PHP file and you should see a side like:
application/zip
application/x-zip
text/plain
text/rtf

YES


As you can see there are two possibilities to check the mime type the first and older one is mime_content_type and the second is finfo_file. It depends on your server installation and with this PHP site you can find your way and you get error messages if there is a problem. These messages will not be shown if you would directly use FacileForms on security reason.

If you know now your accepted mimetype text strings and the function to test it we can implement this in the form under the start submit script. This is possible because if the user submits the form and all javascript checks are passed, the file will be transmitted to the server. So now we have the file in the trusted environment and can check it with our rights. In the following script I check first the security code, then the filesize, than the extension and at last the mimetype. All these function can be tested first if you like (or if you have trouble) with the PHP file above.
Code:
// load the standard Facile Forms library
$this->execPieceByName('ff_InitLib');

// get the name of the uploaded file
$filename = ff_getSubmit('cf_fileupload');

// check attempt to post with invalid security code
if (ff_getSubmit('cf_seccode') != $_SESSION['ff_seccode']) {

    // set a custom error code
    $this->status = 1000;

    // set message for submitted script
    $this->message = 'Invalid security code!';

    // purge uploaded file in case
    if ($filename) unlink($filename);

    // stop processing begin submit piece
    return;
}

// check size of uploaded file
if ($filename && filesize($filename) >= 1000000) {  // 1MB

    // set a custom error code
    $this->status = 1001;

    // set message for submitted script
    $this->message = 'The file size of '.filesize($filename).' bytes is too large!';

    // delete uploaded file
    unlink($filename);

    // stop processing begin submit piece
    return;
}

if ($filename) {
    $extension = substr(strrchr($filename, '.'), 1);
    if (!in_array($extension, explode(',', 'txt,zip'))) {

        // set a custom error code
        $this->status = 1001;

        // set message for submitted script
        $this->message = 'The .'.$extension.' is an invalid file type!';

        // delete uploaded file
        unlink($filename);

        // stop processing begin submit piece
        return;
    }
}

//  application/zip
//  application/x-zip
//  text/plain
//  text/rtf

// $ft = mime_content_type ($image);
// with
// $finfo = finfo_open (FILEINFO_MIME);
// $ft = finfo_file ($finfo, $image);
// finfo_close ($finfo);
// both return "image/gif"

if ($filename) {
    $ft = mime_content_type($filename);
    switch ($ft) {
        case 'application/zip':
        case 'application/x-zip':
        case 'text/plain': 
        case 'text/rtf': 
            break;
        default:
        {
            // set a custom error code
            $this->status = 1001;
   
            // set message for submitted script
            $this->message = 'Sorry .'.$ft.' is an invalid file type!';
   
            // delete uploaded file
            unlink($filename);
   
            // stop processing begin submit piece
            return;
        } // default
    } // switch
}

If one of these tests runs wrong we unlink the file, this means we delete the file and stop all other checks. So for security the file will not be accepted and be deleted. That's secure isn't it?

Last thing, some of you want to mail these files as attachment. This will be done in the script part at the end of transmit. As you can see with the function ff_getSubmit('cf_fileupload') you get the local filename and you can place this as attachment. But please check the error code before otherwise you will have an error if the file didn't pass all the checks.
Code:
// load the standard FacileForms library
$this->execPieceByName('ff_InitLib');
$this->execPieceByName('ff_SubmitLib');
global $mosConfig_lang;
global $mosConfig_absolute_path;
global $mosConfig_live_site;

$filename = ff_getSubmit('cf_fileupload');

if (($filename != '') && ($this->status != 1001)) {
  $attachment = $filename;
  $fileuploadlink = str_replace($mosConfig_absolute_path, $mosConfig_live_site, $filename);
} else {
  $fileuploadlink = '';
  $attachment = null;
} // if

$body = '
<!DOCTYPE HTML PUBLIC "-/W3C/DTD HTML 4.01 Transitional/EN">
<HTML>
<HEAD>
  <META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
</HEAD>
<BODY bgcolor="#EEEEEE">
<br>'.$fileuploadtext.' '.$filename.'<br>
<br>'.$fileuploadtext.' <a href="'.$fileuploadlink.'">'.$fileuploadlink.'</a><br>
<br>'.ff_getSubmit('cf_message').'
</BODY>
</HTML>
'; // end body

$this->sendMail('your@adress.net', // email addr of submitter
  'your name',                     // name of submitter
  ff_getSubmit('cf_email'),        // email of recipient
  'Test mail',                     // subject of the mail
  $body,                           // body of the mail
  $attachment,                     // attachment(s)
  TRUE,                            // send as html
  NULL,                            // email addr of cc
  NULL);                           // email addr of bcc

I also find some threads about a link to the file. Therefore I replace $mosConfig_absolute_path with $mosConfig_live_site and place it in the HTML mail.

So that's all, it works fine for me and hopefully for you and with all these checks it is quit secure.

Have fun and comments are welcome.
Bonvie
« Last Edit: January 05, 2008, 10:16:35 pm by Bonvie » Logged
j_pablo_gn
Full Member
***
Offline Offline

Posts: 143


« Reply #1 on: January 04, 2009, 05:23:36 pm »

Great tutorial.
Thanks, it has helped me a lot.
Logged
schalala
Newbie

Offline Offline

Posts: 2


« Reply #2 on: May 26, 2009, 05:01:25 pm »

Dito. This tutorial helped me create my form with 2 secure upload elements  Cheesy
Thanks a lot!
Logged
Pages: [1]   Go Up
  Print  
 
Jump to:  

Powered by SMF © 2001-2006 Lewis Media
| Terms of Use | Privacy | Sitemap |