Скрипт прокси в PHP, чтобы обойти отсутствующий crossdomain.xml - пропущены незначительные изменения
1-й фон - чтобы вы увидели, что я не пытаюсь ничего вредоносного: у меня есть флеш-приложение в российской социальной сети vkontakte.ru, которое отображает аватары пользователей. До сих пор мой файл.swf размещался в их домене, так что выборка и масштабирование аватаров работали хорошо.
Теперь я хотел бы переключить мое приложение на iframe-тип, чтобы.swf был размещен на моем домене, и поэтому я больше не могу масштабировать аватары в моем.swf: ни мой домен, ни "*"перечислены в http://vkontakte.ru/crossdomain.xml и, следовательно,.swf может загружать и отображать аватары, но больше не может их масштабировать (доступ к myLoader.content вызывает SecurityError).
Я решил написать прокси-скрипт на PHP, который будет получать изображение, указанное в параметре scripts ? 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 () в локальных файлах с моего веб-сервера.
И в качестве дополнительного вопроса: я беспокоюсь, что мой.swf будет не единственным приложением, вызывающим мой proxy.php, но я не могу найти хороший способ его обезопасить (возможно, такого способа нет) - я могу не храните секрет в моем.swf и в.php - потому что.swf можно разобрать.
Спасибо Алекс
1 ответ
Я полагаю, что ваше первое предположение верно, вы отправляете заголовок слишком поздно, или вы не получаете ожидаемые заголовки MIME.
Прежде всего попробуйте войти в MIME с помощью file_put_contents
затем, если вы обнаружите, что уже слишком поздно, чтобы быть полезным, вы можете посмотреть на буферизацию вывода.
Однако, если вы вообще не попали в заголовок, возможно, вы находитесь не в том контексте, возможно, HTTP?
На ваш бонусный вопрос; страница iframe размещена на сервере, на этом сервере вы, вероятно, используете PHP, создайте сеанс с session_start()
, задавать $_SESSION['gotvisit'] = TRUE
(или что-то типа того). Затем получите идентификатор сессии, используя $id = session_id()
, этот идентификатор вы можете теперь передать вашей вспышке со стандартными переменными вспышки. Сделайте, чтобы flash передал эту переменную в запросе изображения, затем в вашем скрипте img сделайте;
session_id($_GET['ses']);
session_start();
if(!isset($_SESSION['gotvisit']))
die('no access');
Удачи тебе.