Hi Moodlers,
I've been working on a proxy script so that Moodle can support XML driven Synchronised Multimedia Integration Language (SMIL) and other forms of XML based learning interactions from within its own file storage system. This may become part if the SWF Activity Module for Moodle 2.5+
- Admins need to enable the File System repositories in Site Admin > Plugins > Repositories > Manage Repositories
- Create a directory for the proxy script to access, e.g. /swfcontent/
- And in Site Admin > Plugins > Activity Modules > SWF set the default content directory to the same, e.g. /repository/swfcontent/
Then files can be accessed through the proxy script thus:
- http://example.com/moodle/mod/swf/file.php?content=mydir/subdir/videos/myvideo.mp4
- http://example.com/moodle/mod/swf/file.php?content=mydir/subdir/audio/audio.mp3
- http://example.com/moodle/mod/swf/file.php?content=mydir/subdir/swf/animation.swf
- etc.
Moodle's regular file manager can be used to upload files to those directories as well as allowing FTP access to upload batches of files in bulk, while maintaining their directory structure as SMIL XML and other XML driven multimedia apps require. The SWF Activity Module can automatically pass in the root URL to the directories, e.g. http://example.com/moodle/mod/swf/file.php?content= and then the SMIL XML files can reference the locations of the files relative to that, e.g.
<video src="mydir/subdir/videos/myvideo.mp4"/>
<audio src="mydir/subdir/audio/audio.mp3"/>
<img src="mydir/subdir/img/image.jpg"/>
<animation src="mydir/subdir/swf/animation.swf"/>
This would mean that entire libraries of media files and SMIL XML files can be uploaded, via FTP and decompressed on the server for immediate deployment. The SWF Activity Module moodle/mod/swf/mod_form.php script can search the libraries for any .xml files and lists them when teachers and course content developers deploy instances of the SWF Activity Module. These libraries would be accessible to anyone who is logged into Moodle so wouldn't be suitable for users' personal files or anything that requires user permissions to access.
The proxy script I have so far is pretty rudimentary and I'm sure that there are issues with it that I haven't thought of. The questions I have are:
What overall improvements can I make to it?
Here's the moodle/mod/swf/file.php script:
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package mod
* @subpackage swf
* @copyright 2013 Matt Bury
* @author Matt Bury <matt@matbury.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
require_login(); // Users must be logged in to access files
global $CFG;
if(isset($_GET['content']))
{
// Clean up content path
$swf_disallowed = array('../','//','///');
$swf_replace = array('','/','/');
$swf_content = str_replace($swf_disallowed,$swf_replace,$_GET['content']);
} else {
header('HTTP/1.0 404 Not Found'); // Send back a 404 so that apps don't wait for a timeout
}
// Make sure all the condtions are met before attempting to server file:
// must have a "." within 5 chacters of the end
if(strrpos($swf_content,'.') > strlen($swf_content) - 6)
{
$swf_file_extention = substr($swf_content,strrpos($swf_content,'.')); // Get file extension to set MIME type
// Build full path to file e.g. /home/sites/example.com/moodledata + /repository/swfcontent/ + videos/myvideo.mp4
$swf_file = $CFG->dataroot.$CFG->swf_content_dir.$swf_content;
} else {
header('HTTP/1.0 404 Not Found');
}
// Serve file
if (file_exists($swf_file) && is_readable($swf_file))
{
// set the MIME type
// Tested in Firefox, Chrome, IE 10, Safari, Opera
// TODO - Test in JW Player and other Flash apps
switch ($swf_file_extention)
{
// AUDIO
case '.aac':
$swf_mime = 'audio/mp4'; // not supported in browsers
break;
case '.f4a':
$swf_mime = 'video/mp4'; // not supported in browsers
break;
case '.m4a':
$swf_mime = 'video/mp4'; // not supported in browsers
break;
case '.mp3':
$swf_mime = 'audio/mpeg';
break;
//IMAGE
case '.gif':
$swf_mime = 'image/gif';
break;
case '.jpeg':
$swf_mime = 'image/jpeg';
break;
case '.jpg':
$swf_mime = 'image/jpeg';
break;
case '.png':
$swf_mime = 'image/png';
break;
// TEXT
case '.smil':
$swf_mime = 'text/xml';
break;
case '.srt':
$swf_mime = 'text/plain';
break;
case '.xml':
$swf_mime = 'text/xml';
break;
// VIDEO
case '.f4v':
$swf_mime = 'video/x-flv'; // not supported in browsers
break;
case '.flv':
$swf_mime = 'video/x-flv';
break;
case '.m4v':
$swf_mime = 'video/x-m4v'; // not supported in browsers
break;
case '.mov':
$swf_mime = 'video/mp4';
break;
case '.mp4':
$swf_mime = 'video/mp4';
break;
// FLASH
case '.swf':
$swf_mime = 'application/x-shockwave-flash';
break;
default:
$swf_mime = false;
}
// if a valid MIME type exists, display the image by sending appropriate headers and streaming the file
if ($swf_mime)
{
header('Content-type: '.$swf_mime);
header('Content-length: '.filesize($swf_file));
$file = @ fopen($swf_file, 'rb');
if ($file)
{
ob_end_clean(); // Prevent large files from exceeding php.ini memory limit
fpassthru($file);
exit;
}
} else {
header('HTTP/1.0 404 Not Found');
}
}
// Closing PHP tag may cause whitespace problems!
How secure is it and if there are any vulnerabilities, how can I fix them?
Thanks in advance!