Hello,
1st the background - so that you see, that I'm not trying anything malicious: I have a flash app in the russian social network vkontakte.ru which displays user avatars. Until now my .swf file has been hosted at their domain, so that fetching and scaling avatars worked well.
Now I'd like to switch my app to an iframe-type, so that the .swf will be hosted at my domain and thus I'm not able to scale the avatars in my .swf anymore: neither my domain, nor "*" are listed in http://vkontakte.ru/crossdomain.xml and thus the .swf can download and display the avatars, but can't scale them anymore (accessing myLoader.content throws SecurityError).
I've decided to write a proxy script in PHP which would fetch the image specified in scripts ?img= parameter and then just pass it to the stdout (after some checks and without storing anything):
<?php
define('MAX_SIZE', 1024 * 1024);
$img = $_GET['img'];
if (strpos($img, '..') !== false ||
!preg_match(',^http://[\w.]*vkontakte\.ru/[\w./?]+$,i', $img))
exit();
$opts = array(
'http'=>array(
'method' => 'GET',
'header' => "Accept-language: en\r\n" .
"Cookie: foo=bar\r\n"
)
);
$ctx = stream_context_create($opts);
stream_context_set_params($ctx, array('notification' => 'callback'));
$fp = fopen($img, 'r', false, $ctx);
fpassthru($fp);
fclose($fp);
function callback($code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
if ($code == STREAM_NOTIFY_FILE_SIZE_IS && $bytes_max > MAX_SIZE)
exit();
if ($code == STREAM_NOTIFY_PROGRESS && $bytes_transferred > MAX_SIZE)
exit();
if ($code == STREAM_NOTIFY_MIME_TYPE_IS) {
$mime = strtolower($message);
switch($message) {
case 'image/gif':
case 'image/png':
case 'image/jpg':
case 'image/jpeg':
// XXX this doesn't work XXX
header('Content-Type: ' . $mime);
break;
default:
exit();
}
}
}
?>
My problem is that the $mime header is never printed (or is printed too late?).
When I fetch for example my avatar directly: http://cs971.vkontakte.ru/u59751265/a_7567890a.jpg then I see the Content-Type: image/jpeg header being sent to the browser.
But when I fetch it through my proxy script, I don't see that header.
Maybe I should better use a different function instead of fopen()? I'm not very proficient in PHP. Also I'm worried if fopen() can be tricked into serving local files from my web server.
And as a bonus question: I'm worried that my .swf will be not the only app calling my proxy.php, but I can't figure out a good way to secure it (maybe there is no such way) - I can't store a secret in my .swf and in the .php - because the .swf can be disassembled.
Thank you, Alex