Skip to content

June 1, 2010

Note on implementing Ajax style hidden IFRAME upload page on FreeBSD 8.0

by Joe Kuan

This problem has taken me a while to track it down. The same code works fine on Ubuntu with IE8, Firefox, Safari but it just doesn’t work on FreeBSD.

For details of implementing a Ajax style upload page, see this. Basically, you have a page with a FORM and a IFRAME, following is an example:

<FORM action='install_upload.php' method=post enctype='multipart/form-data' target=hidden_upload >
<input type=file name='upload_file' >
<INPUT type=submit name=submit value=Upload onclick='return checkUpload();' />
</FORM>
<IFRAME id=hidden_upload name=hidden_upload src='' onLoad='uploadDone( )'
               style='width:500;height:300;border:0px solid #fff'>
</IFRAME>

In this case, I have set the hidden frame dimension to non-zero, so I can see how is happening in behind.

On the PHP side, the install_upload.php is called as soon as the upload is finished and the JSON result is outputed to the hidden IFRAME.

// Some code here to get the install process status and perhaps some log messages
// and assign the result into the $result array
// move_uploaded_file($_FILES[....], ....)
// unpack uploaded file
// run install process in the background
echo json_encode($result);

Once the output text is pushed into the IFRAME, the onLoad event is triggered and Javascript function uploadDone is called. The uploadDone is based on the code in OpenJS.

Problem

When I upload a file on IE8 browser, I get a message,  “Do you want to save this file, or find a program….”. This is totally unexpected, so I looked in the content of the install_upload.php which is the JSON output, very strange.

As for Safari and Firefox, the uploadDone function did not work and reported with a Javascript error but what inside the IFRAME looks legitimate JSON text to me. When I tried to call alert with the content inside the IFRAME. Then it became clear. The JSON text was encapsulated inside a <PRE> tag.

Solution

After a very long while of investigation, I realise the problem is to do with the PHP’s JSON implementation. On FreeBSD 8.0, the PHP JSON has to be installed as a separate PEAR package. The methods json_encode and json_decode are not part of the PHP installation. So I have to do something like this within my web application.

  if ( !function_exists('json_decode') ) {
    function json_decode($content, $assoc=false){
      require_once 'JSON.php';
      if ( $assoc ){
        $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
      } else {
        $json = new Services_JSON;
      }
      return $json->decode($content);
    }
  }

  if ( !function_exists('json_encode') ){
    function json_encode($content){
      require_once 'JSON.php';
      $json = new Services_JSON;
      return $json->encode($content);
    }
  }

Look inside the JSON.php file (/usr/local/share/pear/JSON.php),  here is the code for the encode function:

function encode($var)    {
        header('Content-type: application/x-javascript');
        return $this->_encode($var);
}

The header function call is the culprit which causes all the problems within the IFRAME. However, there is another function within the JSON package which does:

function encodeUnsafe($var) {
        return $this->_encode($var);
}

As soon as I make sure calling encodeUnsafe inside the install_upload.php, all the problems gone away.

I work for iTrinegy. Here are my other blogs on FreeBSD

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments

%d bloggers like this: