User Tools

Site Tools


php:imageproxy

I like PHP. It might not be as speedy as java, C, C++ etc, but it gets the job done (most of the time). I ran a website with a forum, and as we moved to HTTPS only, when people linked to external images they got a warning saying that some content was non-encrypted. I thought about it for a while, and decided to write an “image proxy” as we had plenty of bandwidth and cpu available.

The script grabs an image and saves it on the local disk to serve it via. HTTPS. Voilá, warnings gone. I even built in a 304 option, but had nginx do some of the work for me, so I disabled that again. Rather nginx do some work file-work than PHP. PHP can do it once pr. image, then let nginx handle it from there.

NOTES: You need to change $key + $iv + $imagepath + decide if you want to use proxies. We used 3 internal proxies to bounce calls outside. If you want to disable the proxy calls, just outcomment $proxies + “request_fulluri”. It's not very well documented. If you don't know how to use it, you need more PHP training or alternatively buy some expensive pre-made scripts from people/companies. Your choice :)

imageProxy.php
<?php
if (empty($_GET['imgurl'])) { die(); }
 
// No need to abort if the user does, we need the image anyway.
ignore_user_abort(true);
set_time_limit(90);
 
function decProxyStr($todec) {
// Decrypt this bitch.
	$key = "RyrzDWzNDztgzMzhrtuO";
// Make it look pretty for the other guys. I'd just do one line normally.
	$crypttext = urldecode($todec);
	$crypttext = str_rot13($crypttext);
	$crypttext = str_replace(array('-','_','.'), array('+','/','='), $crypttext);
	$crypttext = base64_decode($crypttext);
	if (strlen($crypttext) > 0) {
// Static IV
		$iv = base64_decode("bjzgz7z9zag=");
// Fetch the rest of the string, this must be data. mmmmmm, dataaaa.
		$crypttext = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $crypttext, MCRYPT_MODE_CBC, $iv);
		return trim($crypttext);
	} else {
// Image here possibly?
		die("Incorrect key");
	}
}
 
function outputImg($imgpath) {
	$imgopt = @getimagesize($imgpath);
	if ($imgopt['mime'] == "image/gif" || $imgopt['mime'] == "image/jpeg" || $imgopt['mime'] == "image/png") {
// 304 not needed, as nginx caches the files for us.
//		$lastmodified = date('D, j M Y G:i:s T', filemtime($imgpath));
// Send a 304?
//		if (strtotime($lastmodified) <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
//			header($_SERVER['SERVER_PROTOCOL']." 304 Not Modified");
//		} else {
// Nope, output the image
			header('Content-type: '.$imgopt['mime']);
			$todayDate = date("Y-m-d");// current date
			$dateOneMonthAdded = strtotime(date("Y-m-d", strtotime($todayDate)) . "+2 weeks"); // How long in the future
			$cachedate = date('D, j M Y G:i:s T', $dateOneMonthAdded);
//		header('Cache-Control: public');
			header('Cache-Control: max-age=28800');
			header('Expires: '.$cachedate);
			header('Last-Modified: '.$lastmodified);
			echo file_get_contents($imgpath);
//		}
	} else {
		header("HTTP/1.0 404 Not Found");
	}
// Cya
	die();
}
 
$imgurl = $_GET['imgurl'];
$limgurl = decProxyStr($imgurl);
$imgpath = "/var/PATH/webcache/".md5($imgurl);
//echo "imgpath = ".$limgurl." ---<br>";
$header  = "User-Agent: BiggiDK ImageCache 0.1\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
 
if (file_exists($imgpath)) {
	outputImg($imgpath);
}
 
// Proxy
$proxies = array("x.x.x.x:3128","x.x.x.y:3128","x.x.x.z:3128");
shuffle($proxies);
$count = 0;
foreach ($proxies as $proxy) {
	$count++;
	$context_options = array (
		'http' => array (
			'method' => 'GET',
			'header'=> $header,
			'proxy' => $proxy,
			'request_fulluri' => True,
			'content' => $dstrm,
			'timeout' => 30
		)
	);
 
	$context = stream_context_create($context_options);
	$content = file_get_contents($limgurl, false, $context);
	if (strlen($content) > 0) {
		if (file_put_contents($imgpath, $content) !== FALSE) {
			outputImg($imgpath);
		}
	} else {
// Error? Show a default error image - Please remember to change this unless the website owner gives you permission to use it.
		if (file_put_contents($imgpath, file_get_contents("http://www.wingchun.edu.au/app_themes/plastic%20blue/scheduler/statusinfo/error.png", false, $context)) !== FALSE) {
			if ($count == count($proxies)) {
				outputImg($imgpath);
			}
//		} else {
//			echo "total failure. -- ".$imgpath;
		}
	}
}
// If the content hasn't been outputed yet, we can assume that something went wrong, or the file simply does not exist. 404, IN YOUR FACE!
header("HTTP/1.0 404 Not Found");
die();
php/imageproxy.txt · Last modified: 2015/08/15 20:56 (external edit)