第一个背景 - 你看,我没有尝试任何恶意:我在俄罗斯社交网络 vkontakte.ru 中有一个显示用户头像的 Flash 应用程序。到目前为止,我的 .swf 文件一直托管在他们的域中,因此获取和缩放头像效果很好。
现在我想将我的应用程序切换到 iframe 类型,以便 .swf 将托管在我的域中,因此我无法再缩放我的 .swf 中的头像:既不是我的域,也不是“* " 在http://vkontakte.ru/crossdomain.xml中列出,因此 .swf 可以下载和显示头像,但不能再缩放它们(访问 myLoader.content 会引发 SecurityError)。
我决定用 PHP 编写一个代理脚本,它将获取脚本?img=参数中指定的图像,然后将其传递给标准输出(经过一些检查并且不存储任何内容):
<?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();
}
}
}
?>
我的问题是 $mime 标头从未打印(或打印太晚?)。
例如,当我直接获取我的头像时: http: //cs971.vkontakte.ru/u59751265/a_7567890a.jpg 然后我看到Content-Type: image/jpeg标头被发送到浏览器。
但是当我通过代理脚本获取它时,我看不到那个标题。
也许我应该更好地使用不同的函数而不是 fopen()?我不是很精通PHP。我还担心 fopen() 是否会被骗从我的 Web 服务器提供本地文件。
作为一个额外的问题:我担心我的 .swf 将不是唯一调用我的 proxy.php 的应用程序,但我想不出保护它的好方法(也许没有这样的方法) - 我可以不要在我的 .swf 和 .php 中存储秘密 - 因为 .swf 可以反汇编。
谢谢你,亚历克斯