2010-10-08 25 views
0

第一背景 - 讓你看到,我沒有嘗試任何惡意:我有一個在俄羅斯社交網絡vkontakte.ru的Flash應用程序,它顯示用戶頭像。到目前爲止,我的.swf文件已被託管在他們的域中,因此取得和縮放比例的頭像運行良好。在PHP中的代理腳本,以規避缺少crossdomain.xml - 缺少小調整

現在我想將我的應用切換到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 直到看見內容類型:image/JPEG頭被髮送給瀏覽器。

但是,當我通過我的代理腳本獲取它時,我沒有看到該標題。

也許我應該更好地使用不同的功能,而不是fopen()?我不擅長PHP。此外,我擔心,如果fopen()可以欺騙從我的Web服務器服務本地文件。

作爲一個額外的問題:我擔心我的.swf將不是唯一的應用程序調用我的proxy.php,但我找不出一個好方法來保護它(也許沒有這樣的方式) - 我無法在.swf和.php中存儲祕密 - 因爲.swf可以反彙編。

謝謝,亞歷克斯

回答

0

我相信你的第一個假設是正確的,你發送的報頭太遲或你沒有得到你所期望的MIME頭。

首先嚐試使用file_put_contents記錄啞劇,然後如果您發現確實已經太遲而無法使用,請參閱output buffering

如果無論如何你根本不會進入頭部,你可能會在wrong context,也許是HTTP?

對於你的獎金問題; iframe的頁面託管在服務器上,在該服務器上,您可能正在運行PHP,使用session_start()創建會話,設置$_SESSION['gotvisit'] = TRUE(或類似的東西)。然後使用$id = session_id()檢索會話ID,您可以使用標準閃存變量將此ID傳遞到閃存。讓閃光燈在圖像請求中傳遞該變量,然後在您的img腳本中執行;

session_id($_GET['ses']); 
session_start(); 
if(!isset($_SESSION['gotvisit'])) 
    die('no access'); 

祝你好運。