обо всем по-немногу...
UnsecurityDisplayLoader - обертка для несекьюрной загрузки дисплей контента
Итак. Понадобилось в очередной раз "обмануть систему" и получить доступ к контенту, к которому с классическим подходом оного не дают. Т.е. нет возможности залить crossdomain.xml, а картинки на сервере страсть какие красивые.
Небольшое отступление:
Я, ни в коем случае, не пропагандирую использование контента без ведома владельца.Необходимо помнить, что у любого контента в сети есть владелец и есть законодательство РФ. Пусть оно и хромое, но тем не менее.
В дебаг-плеере, где безопасность игнорируется мы можем достучаться к любому контенту, который нам нужен. пробуем:
var loadeer:Loader = new Loader(); loadeer.contentLoaderInfo.addEventListener(Event.INIT, _handler); loadeer.load(new URLRequest("http://img.yandex.net/i/www/logo.png")) // надеюсь яндекс не обидится. я их лого использую для обучающих/ознакомительных целей, а не коммерческих. function _handler(e:Event):void{ trace(e.target.loader.content); // [object Bitmap] }
Цитата:
SecurityError: Error #2122: Нарушение изолированной среды: Loader.content: http://cleptoman.ru/test/dr.swf не может осуществить доступ к http://img.yandex.net/i/www/logo.png. Необходим файл политики, но, когда были загружены эти мультимедийные данные, флаг checkPolicyFile не был установлен.
Ну что же, пора немного покурить интернеты. Долго курить не приходится, потому что вспомнил, что на флэшере Димарик проводил изыскания на эту тему, за что ему огромная благодарность и бронзовый памятник.)
Вдохновившись прочтенным закрадывается мыслишка накидать класс-обертку над лоадером для реализации идеи.
собсно продукт:
package ru.cleptoman.net { import flash.display.MovieClip; import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.Loader; import flash.display.LoaderInfo; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.events.SecurityErrorEvent; import flash.net.URLRequest; import flash.system.LoaderContext; import flash.utils.ByteArray; [Event(name = "open", type = "flash.events.Event.OPEN")] [Event(name = "complete", type = "flash.events.Event.COMPLETE")] [Event(name = "init", type = "flash.events.Event.INIT")] [Event(name = "progress", type = "flash.events.ProgressEvent.PROGRESS")] [Event(name = "securityError", type = "flash.events.SecurityErrorEvent.SECURITY_ERROR")] [Event(name = "ioError", type = "flash.events.IOErrorEvent.IO_ERROR")] /** * @langversion Action Script 3.0 * @see http://cleptoman.free-lance.ru * @author Kutov Aleksey aka cleptoman * @version 0.02 * @playerversion 9 * Класс-надстройка над Loader. Предназначен для загрузки медийного контента форматов JPEG,GIF,PNG,SWF при необходимости игнорируя политику безопасности Flash Player. */ public class UnsecurityDisplayLoader extends EventDispatcher{ protected var _loader:Loader; protected var _parameters:Object; protected var _loading:Boolean; protected var _isAfterFirstError:Boolean; protected var _content:DisplayObject; protected var _extractor:IContentExtractor; public function UnsecurityDisplayLoader() { super(); } private function _create():void { _loader = new Loader(); _configHandlers(); } private function _removeHandlers():void { var li:LoaderInfo = _loader.contentLoaderInfo; li.removeEventListener(Event.COMPLETE, _onHandler); li.removeEventListener(Event.INIT, _onHandler); li.removeEventListener(ProgressEvent.PROGRESS, _onHandler); li.removeEventListener(Event.OPEN, _onHandler); li.removeEventListener(IOErrorEvent.IO_ERROR, _onHandler); li.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, _onHandler); } private function _configHandlers():void { var li:LoaderInfo = _loader.contentLoaderInfo; li.addEventListener(Event.COMPLETE, _onHandler); li.addEventListener(Event.INIT, _onHandler); li.addEventListener(ProgressEvent.PROGRESS, _onHandler); li.addEventListener(Event.OPEN, _onHandler); li.addEventListener(IOErrorEvent.IO_ERROR, _onHandler); li.addEventListener(SecurityErrorEvent.SECURITY_ERROR, _onHandler); } private function _skipLoad():void { if (_loader && _loading) { _loader.close(); } _extractor = null; _content = null; _isAfterFirstError = false; _parameters = null; _loading = false; } /** * Пробуем достучаться до content у LoaderInfo. если не получается, то грузим байты методом loadBytes. Пробуем еще раз. если не получается, то думаем,что делать дальше с ексепшном ) * @param e */ private function _onHandler(e:Event):void { if (e.type === Event.INIT) { if (_isAfterFirstError) { _content = _extractor.extract(_loader.content); _isAfterFirstError = false; }else{ try{ _content = _loader.content; }catch (err:SecurityError) { _extractor = (_loader.contentLoaderInfo.contentType.substring(0,5) === "image") ? new BitmapExtractor() : new MovieClipExtractor(); _isAfterFirstError = true; _loader.loadBytes(_loader.contentLoaderInfo.bytes); e.stopPropagation(); return; } _parameters = _loader.contentLoaderInfo.parameters; } _loading = false; } if (e.type === ProgressEvent.PROGRESS && _isAfterFirstError) { return; } super.dispatchEvent(e); } public override function dispatchEvent (event:Event) : Boolean { throw new Error("Класс не реализует данный метод"); } /** * @return Возвращает последний объект, переданный в URLReqest#data в метод load. Не равен content.loaderInfo.parameters, если загрузка прошла игнорируя безопасность. */ public function get parameters():Object { return _parameters; } /** * @return Возвращает медийный контент. Если загрузка произошла игнорируя политику безопасности, то content.loaderInfo.contentType для объектов будет application/x-shockwave-flash, а не image/jpeg. */ public function get content():DisplayObject { return _content; } /** * @return Возвращает состояние: происходит загрузка в данный момент или нет. */ public function get loading():Boolean { return _loading; } public function load(request:URLRequest,context:LoaderContext = null):void { _skipLoad(); if (!_loader) { _create(); } _parameters = request.data; _loader.load(request,context); _loading = true; } public function loadBytes(bytes:ByteArray):void { _skipLoad(); if (!_loader) { _create(); } _parameters = _loader.contentLoaderInfo.parameters; _loader.loadBytes(bytes); _loading = true; } public function unload():void { _skipLoad(); if(_loader){ _loader.unload(); } } public function unloadAndStop(gc:Boolean = true):void { _skipLoad(); if(_loader){ _loader.unloadAndStop(gc); } } public function close():void { _skipLoad(); } /** * Удаляет внутренние ссылки на используемые объекты. сохраните ссылку на полученный в ходе загрузки content перед вызовом метода */ public function destroy():void { if (_loader) { _skipLoad(); _removeHandlers(); _loader = null; } } } } import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; interface IContentExtractor { function extract(content:DisplayObject):DisplayObject; } class BitmapExtractor implements IContentExtractor { public function extract(content:DisplayObject):DisplayObject { return (content as DisplayObjectContainer).getChildAt(0); } } class MovieClipExtractor implements IContentExtractor { public function extract(content:DisplayObject):DisplayObject { return content; } }
package { import flash.display.Bitmap; import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.net.URLRequest; import ru.cleptoman.net.UnsecurityDisplayLoader; /** * ... * @author Kutov Aleksey aka cleptoman */ public class Main extends Sprite { public function Main():void { if (stage) init(); else stage.addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { super.removeEventListener(Event.ADDED_TO_STAGE, init); var loader:UnsecurityDisplayLoader = new UnsecurityDisplayLoader(); loader.addEventListener(Event.INIT, _onComplete); var req:URLRequest = new URLRequest("http://img.yandex.net/i/www/logo.png"); loader.load(req); } private function _onComplete(e:Event):void { var loader:UnsecurityDisplayLoader = e.target as UnsecurityDisplayLoader; this.addChild(new Bitmap((loader.content as Bitmap).bitmapData)); } } }
класс особо в коментариях не нуждается. основной интерес, возможно, представляет метод _onHandler, обработчик событий.
private function _onHandler(e:Event):void { if (e.type === Event.INIT) { if (_isAfterFirstError) { _content = _extractor.extract(_loader.content); _isAfterFirstError = false; }else{ try{ _content = _loader.content; }catch (err:SecurityError) { _extractor = (_loader.contentLoaderInfo.contentType.substring(0,5) === "image") ? new BitmapExtractor() : new MovieClipExtractor(); _isAfterFirstError = true; _loader.loadBytes(_loader.contentLoaderInfo.bytes); e.stopPropagation(); return; } _parameters = _loader.contentLoaderInfo.parameters; } _loading = false; } if (e.type === ProgressEvent.PROGRESS && _isAfterFirstError) { return; } super.dispatchEvent(e); }
Итак:
По событию INIT смотрим флаг _isAfterFirstError. если он false, значит ошибок безопасности еще не было, отработает блок else. Тут интересней. Как упоминалось выше в примере, в случае нарушения изолированной среды нам выкинет SecurityError.
Это и используем. если выполнился блок try - дальше все идет по плану. Если нет, то отработает catch блок: выставит флаг _isAfterFirstError в true и попробует загрузить полученные байты (благо лоадерИнфо нам их оставил, за что ему и спасибо).
Интересный момент с конвертацией из Bitmap в MovieClip при загрузке байтов картинки. Он описан в вдохновении. Я , исходя из contentType выбираю нужное поведение, которое будет работать чуть ниже.
Еще один интересный момент заключается в том, что, если убрать строку e.stopPropagation();, то каким то неведомым образом INIT редиспатчится выше, где в обработчике пытаюсь взять контент, которого еще и получаю фейл. Если кому-то будет не лень покурить этот момент - будет супер.
Теперь при следующем INIT с нашим флагом _isAfterFirstError == true мы используем экземпляр _extractor, выбраный чуть выше.
Свойство parameters в случае с несекьюрной загрузкой будет просто хранилищем параметров, переданных в метод load и никакого отношения к LoaderInfo#parameters иметь не будет. Эдакий легализованный вагон с гестарбайтерами в составе поезда ФМС ). потому тут надо быть аккуратным или попросту удалить это свойство.
Собственно, полезность метода loadBytes тоже под вопросом.
Вот и все.
Выражаю благодарности dimarik за идею и Psycho Tiger за предварительную рецензию).
Если кому пригодится - хорошо. Не пригодится - значит название моего блога выбрано удачно ).
п.с. Ага, сбаянил)
Всего комментариев 70
Комментарии
22.02.2011 16:46 | |
ну об этом демагогия с предыдущей страницы ))
|
22.02.2011 16:48 | |
Да. Действительно, стоило читать больше.
Извините за ньюбизм. Сижу сейчас как дурак и думаю, где же можно это похитрее применить |
23.02.2011 00:24 | |
Я давно этого ждал. BlooDHounD vs in4core. Спасибо!
@Блуд, вот ты сказал что throw иногда выкидывает null. Имеешь ввиду throw null? А зачем такое может понадобится? |
23.02.2011 00:49 | |
Цитата:
Я давно этого ждал. BlooDHounD vs in4core. Спасибо!
|
23.02.2011 01:05 | |
Цитата:
Мы стараемся чтобы форум привлекал все больше посетителей ))) мы смеемся потому, что...
|
23.02.2011 04:51 | |
возможно ты не заметил, но я тоже выкидываю.
|
23.02.2011 12:03 | |
Я имею ввиду что я всегда в случае чего выкидываю RealError сразу, с подробным описанием проблемы, а не просто констатируя факт что юзер ошибся.
|
23.02.2011 15:20 | |
а толку? =)
|
23.02.2011 16:39 | |
В дебаг версии толку действительно нет, а вот в браузере мы не поймём, в каком из двух методов произошел эксепш.
|
23.02.2011 20:16 | |
Ага, именно. unhandled error ловлю и хоть примерно можно понять, из за чего оно произошло. Я не Бог ведь )
|
23.02.2011 20:33 | |
мдя ... вы кажись не понимаете. ну да ладно.
|
23.02.2011 22:50 | |
Блуд, тогда объясни пожалуйста.
|
23.02.2011 23:46 | |
да я уже написал всё на предыдущей странице.
|
24.02.2011 03:41 | |
Богу не свойственно объяснять, ему свойственно делать..............
|
24.02.2011 20:03 | |
Ну да, я понял о чем ты. Наверное, не правильно высказал свои мысли, ну да ладно.
|
05.04.2011 17:16 | |
здраствуйте, вот интересует, а что поменять, что б грузило HTML страницу???
|
05.04.2011 19:42 | |
Loader на URLLoader. =)
|
Последние записи от cleptoman
- Starling Builder. Дождались? (28.10.2015)
- Starling. Particles. StarMaker... (05.12.2012)
- FLVEncoder (02.08.2011)
- UnsecurityDisplayLoader - обертка для несекьюрной загрузки дисплей контента (12.02.2011)
- ASDoc Comment Injector (08.02.2011)