Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > dimarik

Рейтинг: 4.82. Голосов: 11.

Loader vs FP security.

Запись от dimarik размещена 23.06.2010 в 14:00
Обновил(-а) dimarik 12.10.2012 в 00:29

Если нельзя, но очень хочется, то можно. Крылатая фраза.

Иногда возникает желание загрузить в приложение изображение с чужого сайта. Казалось бы, нет проблем. new Loader() и вперед!
И ведь загрузит. Однако при попытке обратиться к свойству content или скопировать пиксели методом BitmapData#draw() для реализации, например, DragManager, нас может ожидать разочарование. На чужом сайте просто забыли создать для вас файл политик crossdomain.xml или таковой существует, но отсутствует заветная строчка, разрешающая доступ из вашего домена, т.н. разрешение распространителя.

Ну что ж, поробуем разобраться с этой проблемой.

Дано.
Наше приложение (swf), расположенное в песочнице REMOTE.

Задача.
Загрузить в приложение изображение JPEG, GIF или PNG с другого домена и отрисовать его в произвольный DisplayObject методом BitmapData#draw().

Эксперименты проводились с FP 10 и FP 10.1

Для начала загрузим изображение с помощью Loader стандартным путем.
После окончания загрузки обратимся к свойству bytes объекта LoaderInfo нашего лоадера.

Код AS3:
loader.contentLoaderInfo.bytes
Сделав нехитрый дамп этого ByteArray можно обнаружить, что изображение превратилось в... swf структуру.

В этой структуре присутствует сигнатура FWS и версия файла 8. Далее описан обязательный недотег FileAttributes (69).

Следом идет тег DefineBitsJPEG4 (90), содержащий изображение как есть.

Затем тег Unknown (85). Что это такое - неизвестно. Честно признаюсь, смотрел только в официальной документации и у swf alexref. Оба источника молчат как партизаны. По содержанию он похож на DefineShape (2): указан ShapeId, ссылающийся на картинку, затем указано либо количество кадров как у DefineSprite (39), либо ID получившегося объекта. Но тут еще можно учесть, что Loader#content имеет тип Bitmap. Последним параметром, похоже, является ShapeBounds типа RECT. Но это мои предположения.

Ну и заключает структуру тег ShowFrame (1).
Что удивительно, тег End (0) отсутствует.


При желании можно сохранить содержимое bytes на диск и открыть флешплеером. Вы увидите исходное изображение.

Но раз этот bytearray представляет собой swf, то ничто не мешает нам загрузить его повторно методом Loader#loadBytes().
Только учтите, что теперь Loader#content будет иметь тип MovieClip!

Итак, дописываем
Код AS3:
var li:LoaderInfo = loader.contentLoaderinfo;
li.addEventListener(Event.COMPLETE, this.handler_bytesComplete);
loader.loadBytes(li.bytes);
 
function handler_bytesComplete(event:Event):void {
	var source:	DisplayObject = li.content as DisplayObject;
	var bitmapData:	BitmapData = new BitmapData(source.width, source.height, true, 0x00000000);
	var bitmap:	Bitmap = new Bitmap(bitmapData);
 
	bitmapData.draw(source);
	super.addChild(bitmap);
}
Теперь все пиксели под полным контролем.

Идея не нова и ранее была озвучена Денисом на нашем форуме. Я попытался проанализировать почему эта фича работает для картинок.

UPD: С выходом FP 11.4 этот хак перестал работать. Дело в том, что изменилось поведение объектов LoaderInfo. Cодержимое LoaderInfo#bytes будет равно null, если загружаемая картинка принадлежит другому домену и отсутствует разрешение распространителя. Аминь!

UPD: Комрад i.o. Обнаружил дыру, с помощью которой все-таки можно загрузить ансекурный контент-изображение. Только не забудьте разрешить кросскриптинг с этого домена (Security.allowDomain('http://example.com')). Амень!
Всего комментариев 22

Комментарии

Старый 23.06.2010 15:27 iNils вне форума
iNils
 
Аватар для iNils
Красота.
Старый 25.06.2010 15:06 koIIImarik вне форума
koIIImarik
 
Аватар для koIIImarik
Очень интересный пост. Конечно, по-сути, это хак, и, скорее всего, в будущем, Adobe будет стараться его прикрыть, но сам тот факт, что у вас его получилось найти — это очень круто.

Хотел бы у вас поинтересоваться на счёт одного вопроса. Перед нашей командой разработчиков сейчас стоит задача организовать возможность «снятия» скриншотов с игр. Из-за того, что игры подгружаются с других сайтов, и, плюс, сами загружаемые флешки подгружают в себя флешки с других сайтов (наподобие модулев для оплаты разных фишек внутри игр от MochiAds), при попытке снять скриншот с клипа, где находится игра, выдаётся ошибка безопасности (мол хотите обратиться к данным, с неразрешённого сайта и т.п.).

Как вы думаете:
1) Можно ли будет тем способом, что вы описали снимать скриншоты с загруженных .swf файлов?

2) Так как скриншоты должны будут сниматься не в самом начале, а в процессе игры, будет ли свойство .bytes у объекта LoaderInfo отражать текущую картину загруженной игры?

Буду вам очень благодарен за ответ.
Старый 25.06.2010 17:27 dimarik вне форума
dimarik
 
Аватар для dimarik
1) Если ваша флешка играется в песочнице REMOTE, то из-за того, что сами загружаемые флешки подгружают в себя флешки с других сайтов, не получится снять скриншот. Если, конечно, внутри последних не прописан правильный Security.allowDomain(). Например, Security.allowDomain("*").

2) Это свойство содержит swf-файл, а не текущую картинку игры.
Старый 25.06.2010 17:50 koIIImarik вне форума
koIIImarik
 
Аватар для koIIImarik
2) Это свойство содержит swf-файл, а не текущую картинку игры.
Под «текущей каринкой игры», я понимал картинку, которая будет внутри загруженного .swf файла, на момент снятия скриншота. Грубо говоря, интересует, будет ли изменяться свойство bytes, если внутри загруженной флешки что-то изменится? Или bytes отражают состояние .swf файла на момент загрузки?
Старый 25.06.2010 18:04 dimarik вне форума
dimarik
 
Аватар для dimarik
bytes отражает содержимое свф файла. Свф файл в процессе исполнения не изменяется.
Обновил(-а) dimarik 25.06.2010 в 18:22
Старый 25.06.2010 18:25 koIIImarik вне форума
koIIImarik
 
Аватар для koIIImarik
Ок, спасибо, т.е. на сколько я понял таким образом снять скриншот не получится. Ведь мне нужно будет «снимать» изменения, которые происходят внутри загруженного .swf файла (читай внутри Sprite, в который загрузили флешку).
Старый 25.06.2010 18:34 dimarik вне форума
dimarik
 
Аватар для dimarik
Скриншот нужно снимать методом BitmapData#draw()
Старый 30.06.2010 12:03 TimID вне форума
TimID
 
Аватар для TimID
2 koIIImarik, Вашу задачу может помочь решить пакет f-in-box.
Он позволяет встраивать флеш-преер в любое приложение, например, на visual basic, сохраняя его полную работоспособность.
На сайте есть множество примеров, в том числе и по снятию скриншотов, и по управлению проигрыванием мувиков.
Старый 06.08.2010 18:17 nbvehfuanet вне форума
nbvehfuanet
Код AS3:
var loader:Loader = new Loader();
 
 
loader.load( new URLRequest('http://img.yandex.net/i/www/logo.png'));
 
var li:LoaderInfo = loader.contentLoaderInfo;
li.addEventListener(Event.COMPLETE,handler_bytesComplete);
loader.loadBytes(li.bytes);
 
function handler_bytesComplete(event:Event):void {
	var source:	DisplayObject = li.content as DisplayObject;
	var bitmapData:	BitmapData = new BitmapData(source.width, source.height, true, 0x00000000);
	var bitmap:	Bitmap = new Bitmap(bitmapData);
 
	bitmapData.draw(source);
	super.addChild(bitmap);
}
при попытке скомпилировать код выходит ошибка и всё закрываеться,что в этом коде не так?помогите пожалуста разобраться
Старый 06.08.2010 20:46 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Вы дождитесь загрузки
Код AS3:
loader.load( new URLRequest('http://img.yandex.net/i/www/logo.png'));
то
Старый 06.08.2010 23:40 nbvehfuanet вне форума
nbvehfuanet
Код AS3:
var loader:Loader = new Loader();
 
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void
{
   var li:LoaderInfo = loader.contentLoaderInfo;
li.addEventListener(Event.COMPLETE, handler_bytesComplete);
loader.loadBytes(li.bytes);
 function handler_bytesComplete(event:Event):void {
	var source:	DisplayObject = li.content as DisplayObject;
	var bitmapData:	BitmapData = new BitmapData(source.width, source.height, true, 0x00000000);
	var bitmap:	Bitmap = new Bitmap(bitmapData);
 
	bitmapData.draw(source);
	addChild(bitmap);
}
 
});
loader.load( new URLRequest('http://img.yandex.net/i/www/logo.png'));
так тоже почему то не работаетподскажите что нужно изменить чтобы наконец то заработало
Старый 07.08.2010 13:02 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Попробуйте для начала писать без замыканий и вложенных функций, а потом боритесь с работоспособностью.
Старый 07.08.2010 20:26 nbvehfuanet вне форума
nbvehfuanet
может быть дело в том что я загружаю флешку вконтакт,там что то другое мешает загрузить мне изображение?
Старый 07.08.2010 20:30 nbvehfuanet вне форума
nbvehfuanet
всё,разобрался
каких то 4 дня с кофем в обнимку и готово))
вот что у меня вышло,мб атким же новечкам как я поможет
Код AS3:
var loader:Loader = new Loader();
 
 
loader.load( new URLRequest('http://cs4538.vkontakte.ru/u14300603/a_403ee368.jpg'));
 
var li:LoaderInfo = loader.contentLoaderInfo;
li.addEventListener(Event.COMPLETE,handler_bytesComplete);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,comp); 
										  function comp(e:Event):void
{
loader.loadBytes(li.bytes);
}
function handler_bytesComplete(event:Event):void {
	var source:	DisplayObject = li.content as DisplayObject;
	var bitmapData:	BitmapData = new BitmapData(source.width, source.height, true, 0x00000000);
	var bitmap:	Bitmap = new Bitmap(bitmapData);
 
	bitmapData.draw(source);
	super.addChild(bitmap);
}
Старый 29.08.2010 16:13 i.o. вне форума
i.o.
 
Аватар для i.o.
А разве нельзя загрузить картинку сначала через URLLoader или URLStream, а потом уже Loader#loadBytes()?
Тогда байты не модифицируются.

Или я что-то упускаю из виду?
Старый 29.08.2010 17:19 RAlfDog вне форума
RAlfDog
 
Аватар для RAlfDog
Крутт-о-o-o!
Очень актуально!
Сегодня же испробую этот рецепт
Старый 19.10.2010 11:48 cleptoman вне форума
cleptoman
 
Аватар для cleptoman
i.o., без кроссдомена URLLoader, вроде, совсем не пройдет запрос
Старый 03.03.2012 14:58 Андрей911 вне форума
Андрей911
 
Аватар для Андрей911
Класс! Интересно когда-нибудь прикроют или нет? Только что попробовал в FP11 еще работает.
Старый 05.03.2012 01:05 etc вне форума
etc
 
Аватар для etc
На 1.5 года ранее (относительно поста) упоминалась эта чудо-фича: http://www.flasher.ru/forum/showpost...92&postcount=5
Старый 05.03.2012 01:43 dimarik вне форума
dimarik
 
Аватар для dimarik
Поправил. Несколько лишними там выглядят манипуляции с флагом checkPolicy=true (даст загрузить картинку без ведома политики, но крадет время на загрузку crossdomain.xml, который нам не нужен) и с LoaderContext (аппдомен там такой, что картинка никогда не выгрузится из памяти)
Обновил(-а) dimarik 07.03.2012 в 21:47
Старый 31.05.2012 22:15 Acrossfy вне форума
Acrossfy
 
Аватар для Acrossfy
Решил спустя время подправить решение nbvehfuanet для iFrame приложений vk.com, которое приводило к бесконечной загрузке данных и добавлению элементов, что адски загружало процессор:
Код AS3:
var loader:Loader = new Loader();
loader.load( new URLRequest(url));
 
var li:LoaderInfo = loader.contentLoaderInfo;
li.addEventListener(Event.COMPLETE, handler_bytesComplete);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, comp); 
 
function complete(e:Event):void
{
	loader.loadBytes(li.bytes);
	loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, comp);
}
 
function handler_bytesComplete(event:Event):void
{
	var source:DisplayObject = li.content as DisplayObject;
	var bitmapData:BitmapData = new BitmapData(source.width, source.height, true, 0x00000000);
	var bitmap:Bitmap = new Bitmap(bitmapData);
 
	bitmapData.draw(source);
	addChild(bitmap);
}
Старый 13.02.2013 16:30 Борис Бритва вне форума
Борис Бритва
ссылка из UPD: №2 не работает. Что же за хитрое решение там было?
 

 


Часовой пояс GMT +4, время: 16:38.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2020, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.