Скрипт прокси в 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');

Удачи тебе.

Другие вопросы по тегам