Loader vs FP security.
Если нельзя, но очень хочется, то можно. Крылатая фраза.
Иногда возникает желание загрузить в приложение изображение с чужого сайта. Казалось бы, нет проблем. new Loader() и вперед!
И ведь загрузит. Однако при попытке обратиться к свойству content или скопировать пиксели методом BitmapData#draw() для реализации, например, DragManager, нас может ожидать разочарование. На чужом сайте просто забыли создать для вас файл политик crossdomain.xml или таковой существует, но отсутствует заветная строчка, разрешающая доступ из вашего домена, т.н. разрешение распространителя.
Ну что ж, поробуем разобраться с этой проблемой.
Дано.
Наше приложение (swf), расположенное в песочнице REMOTE.
Задача.
Загрузить в приложение изображение JPEG, GIF или PNG с другого домена и отрисовать его в произвольный DisplayObject методом BitmapData#draw().
Эксперименты проводились с FP 10 и FP 10.1
Для начала загрузим изображение с помощью Loader стандартным путем.
После окончания загрузки обратимся к свойству bytes объекта LoaderInfo нашего лоадера.
Сделав нехитрый дамп этого 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!
Итак, дописываем
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 | |
Красота.
|
25.06.2010 18:04 | |
bytes отражает содержимое свф файла. Свф файл в процессе исполнения не изменяется.
|
|
Обновил(-а) dimarik 25.06.2010 в 18:22
|
25.06.2010 18:34 | |
Скриншот нужно снимать методом BitmapData#draw()
|
30.06.2010 12:03 | |
2 koIIImarik, Вашу задачу может помочь решить пакет f-in-box.
Он позволяет встраивать флеш-преер в любое приложение, например, на visual basic, сохраняя его полную работоспособность. На сайте есть множество примеров, в том числе и по снятию скриншотов, и по управлению проигрыванием мувиков. |
06.08.2010 20:46 | |
07.08.2010 13:02 | |
Попробуйте для начала писать без замыканий и вложенных функций, а потом боритесь с работоспособностью.
|
07.08.2010 20:26 | |
может быть дело в том что я загружаю флешку вконтакт,там что то другое мешает загрузить мне изображение?
|
29.08.2010 16:13 | |
А разве нельзя загрузить картинку сначала через URLLoader или URLStream, а потом уже Loader#loadBytes()?
Тогда байты не модифицируются. Или я что-то упускаю из виду? |
29.08.2010 17:19 | |
Крутт-о-o-o!
Очень актуально! Сегодня же испробую этот рецепт |
19.10.2010 11:48 | |
i.o., без кроссдомена URLLoader, вроде, совсем не пройдет запрос
|
03.03.2012 14:58 | |
Класс! Интересно когда-нибудь прикроют или нет? Только что попробовал в FP11 еще работает.
|
05.03.2012 01:05 | |
На 1.5 года ранее (относительно поста) упоминалась эта чудо-фича: http://www.flasher.ru/forum/showpost...92&postcount=5
|
05.03.2012 01:43 | |
Поправил. Несколько лишними там выглядят манипуляции с флагом checkPolicy=true (даст загрузить картинку без ведома политики, но крадет время на загрузку crossdomain.xml, который нам не нужен) и с LoaderContext (аппдомен там такой, что картинка никогда не выгрузится из памяти)
|
|
Обновил(-а) dimarik 07.03.2012 в 21:47
|
13.02.2013 16:30 | |
ссылка из UPD: №2 не работает. Что же за хитрое решение там было?
|
Последние записи от dimarik
- Memory allocation на Vector.<IInterface> (07.05.2015)
- [Starling] Тормози меня плавно! (28.10.2014)
- [Starling идиотизмы] Об интерактивных событиях (02.10.2014)
- О типах исключений. (23.04.2014)
- Немного о Vector и ByteArray (28.03.2014)