Hi MODx community,
I’m in the process of upgrading a website, originally built in Evo 0.9.6.3, to Evo 1.0.4, and as part of that I’m trying to consolidate into a plugin a set of scripts that we had written externally. The process included an insertion into /manager/processors/save_content.processor.php at line 270, which replaced standard direct links to files with a link to another php script. Here’s the code:
$content = str_replace("img src=\\\"assets/secure/", "img src=\\\"/image.php?image=/", $content);
$content = str_replace("a href=\\\"assets/secure/", "a href=\\\"/file.php?file=/", $content);
$content = str_replace("EMBED SRC=\\\"assets/secure/", "EMBED SRC=\\\"/video.php?video=/", $content);
The script, as you can see, causes a secure folder contained within assets to be obfuscated, meaning that the external php scripts (image.php, file.php and video.php) do the work of pulling the files out for either download or view.
[table]
[tr]
[td]
image.php
[/td]
[td]
file.php
[/td]
[td]
video.php
[/td]
[/tr]
[tr]
[td]
//script to draw images from secure folder
// Define base directory top level to secure files
define('BASE_PATH', getcwd()."/assets/secure/images");
if(!isset($_GET['image']))
{
die("No access unset GET");
}
// get target directory within assets/images
$dir = dirname($_GET['image']);
if(!is_dir(BASE_PATH.$dir))
{
die("No access no such dir ".BASE_PATH.$dir);
}
chdir(BASE_PATH.$dir);
if(substr(getcwd(),0,strlen(BASE_PATH)) != BASE_PATH)
{
die("Incorrect cwd");
}
if(file_exists(BASE_PATH.$_GET['image']))
{
$type = substr($_GET['image'], strrpos($_GET['image'], '.') + 1);
header("Content-Type: image/".strtolower($type));
readfile(BASE_PATH.$_GET['image']);
}
[/td]
[td]
//script to draw files from secure folder
// Define base directory top level to secure files
define('BASE_PATH', getcwd()."/assets/secure/files");
if(!isset($_GET['file']))
{
die("No access unset GET");
}
// get target directory within assets/secure/images
$dir = dirname($_GET['file']);
if(!is_dir(BASE_PATH.$dir))
{
die("No access no such dir ".BASE_PATH.$dir);
}
chdir(BASE_PATH.$dir);
if(substr(getcwd(),0,strlen(BASE_PATH)) != BASE_PATH)
{
die("Incorrect cwd");
}
if(file_exists(BASE_PATH.$_GET['file']))
{
$type = substr($_GET['file'], strrpos($_GET['file'], '.') + 1);
header("Cache-Control: public, must-revalidate");
header("Pragma: hack");
header("Content-Type: application/octet-stream");
header("Content-Length: " .(string)(filesize(BASE_PATH.$_GET['file'])) );
header('Content-Disposition: attachment; filename="'.basename($_GET['file']).'"');
ob_start();
$fh = fopen(BASE_PATH.$_GET['file'], 'r');
while(!feof($fh))
{
print fread($fh, 8192);
set_time_limit(0);
ob_flush();
}
fclose($fh);
exit;
}
[/td]
[td]
//script to draw media from secure folder
// Define base directory top level to secure files
define('BASE_PATH', getcwd()."/assets/secure/media");
if(!isset($_GET['media']))
{
die("No access unset GET");
}
// get target directory within assets/secure/media
$dir = dirname($_GET['media']);
if(!is_dir(BASE_PATH.$dir))
{
die("No access no such dir ".BASE_PATH.$dir);
}
chdir(BASE_PATH.$dir);
if(substr(getcwd(),0,strlen(BASE_PATH)) != BASE_PATH)
{
die("Incorrect cwd");
}
if(file_exists(BASE_PATH.$_GET['media']))
{
$type = substr($_GET['media'], strrpos($_GET['media'], '.') + 1);
header("Content-Type: video/mpeg"); //" . strtolower($type));
header("Content-Length: " .(string)(filesize(BASE_PATH.$_GET['media'])) );
header("Expires: -1");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
readfile(BASE_PATH.$_GET['media']);
}
[/td][/tr][/table]
This system has worked very well for me in securing contextual files and images. However, when I was looking through save_content.processor.php, I noticed that just before lines 270 and line 450, where the code is used again, the OnBeforeDocFormSave event is called. So, for the upgrade, I’ve taken that 1st script and added it to a plugin that actions on the OnBeforeDocFormSave event. That was kinda simple.
But what I’d like to do is take those external scripts - file.php, image.php and video.php - and also integrate them into either the same plugin or a snippet or something. However, I can’t see how to do this, as this links require a landing point that contains the external script(s) and works with the php headers that are being sent for each of the file types. Also, if I were to use a plugin, how do I put the page id into that script, along with the other $_GET information that’s required; and what event do I use to put the external scripts into?
Rather complex situation maybe, would be happy to provide more info if required.