root/as3/ForcibleLoader/src/org/libspark/utils/ForcibleLoader.as

リビジョン 3232, 5.5 kB (コミッタ: yossy, コミット時期: 4 ヶ月 前)

ForcibleLoader?: Fixed behavior of flagSWF9Bit method if SWF has no FileAttribute? tag.

Line 
1 /*
2  * ForcibleLoader
3  *
4  * Licensed under the MIT License
5  *
6  * Copyright (c) 2007-2009 BeInteractive! (www.be-interactive.org) and
7  *                         Spark project  (www.libspark.org)
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  *
27  */
28 package org.libspark.utils
29 {
30         import flash.display.Loader;
31         import flash.net.URLRequest;
32         import flash.net.URLStream;
33         import flash.events.IOErrorEvent;
34         import flash.events.SecurityErrorEvent;
35         import flash.events.Event;
36         import flash.utils.ByteArray;
37         import flash.utils.Endian;
38         import flash.errors.EOFError;
39        
40         /**
41          * Loads a SWF file as version 9 format forcibly even if version is under 9.
42          *
43          * Usage:
44          * <pre>
45          * var loader:Loader = Loader(addChild(new Loader()));
46          * var fLoader:ForcibleLoader = new ForcibleLoader(loader);
47          * fLoader.load(new URLRequest('swf7.swf'));
48          * </pre>
49          *
50          * @author yossy:beinteractive
51          * @see http://www.be-interactive.org/?itemid=250
52          * @see http://fladdict.net/blog/2007/05/avm2avm1swf.html
53          */
54         public class ForcibleLoader
55         {
56                 public function ForcibleLoader(loader:Loader)
57                 {
58                         this.loader = loader;
59                        
60                         _stream = new URLStream();
61                         _stream.addEventListener(Event.COMPLETE, completeHandler);
62                         _stream.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
63                         _stream.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
64                 }
65                
66                 private var _loader:Loader;
67                 private var _stream:URLStream;
68                
69                 public function get loader():Loader
70                 {
71                         return _loader;
72                 }
73                
74                 public function set loader(value:Loader):void
75                 {
76                         _loader = value;
77                 }
78                
79                 public function load(request:URLRequest):void
80                 {
81                         _stream.load(request);
82                 }
83                
84                 private function completeHandler(event:Event):void
85                 {
86                         var inputBytes:ByteArray = new ByteArray();
87                         _stream.readBytes(inputBytes);
88                         _stream.close();
89                         inputBytes.endian = Endian.LITTLE_ENDIAN;
90                        
91                         if (isCompressed(inputBytes)) {
92                                 uncompress(inputBytes);
93                         }
94                        
95                         var version:uint = uint(inputBytes[3]);
96                        
97                         if (version < 9) {
98                                 updateVersion(inputBytes, 9);
99                         }
100                         if (version > 7) {
101                                 flagSWF9Bit(inputBytes);
102                         }
103                         else {
104                                 insertFileAttributesTag(inputBytes);
105                         }
106                        
107                         loader.loadBytes(inputBytes);
108                 }
109                
110                 private function isCompressed(bytes:ByteArray):Boolean
111                 {
112                         return bytes[0] == 0x43;
113                 }
114                
115                 private function uncompress(bytes:ByteArray):void
116                 {
117                         var cBytes:ByteArray = new ByteArray();
118                         cBytes.writeBytes(bytes, 8);
119                         bytes.length = 8;
120                         bytes.position = 8;
121                         cBytes.uncompress();
122                         bytes.writeBytes(cBytes);
123                         bytes[0] = 0x46;
124                         cBytes.length = 0;
125                 }
126                
127                 private function getBodyPosition(bytes:ByteArray):uint
128                 {
129                         var result:uint = 0;
130                        
131                         result += 3; // FWS/CWS
132                         result += 1; // version(byte)
133                         result += 4; // length(32bit-uint)
134                        
135                         var rectNBits:uint = bytes[result] >>> 3;
136                         result += (5 + rectNBits * 4) / 8; // stage(rect)
137                        
138                         result += 2;
139                        
140                         result += 1; // frameRate(byte)
141                         result += 2; // totalFrames(16bit-uint)
142                        
143                         return result;
144                 }
145                
146                 private function findFileAttributesPosition(offset:uint, bytes:ByteArray):int
147                 {
148                         bytes.position = offset;
149                        
150                         try {
151                                 for (;;) {
152                                         var byte:uint = bytes.readShort();
153                                         var tag:uint = byte >>> 6;
154                                         if (tag == 69) {
155                                                 return bytes.position - 2;
156                                         }
157                                         var length:uint = byte & 0x3f;
158                                         if (length == 0x3f) {
159                                                 length = bytes.readInt();
160                                         }
161                                         bytes.position += length;
162                                 }
163                         }
164                         catch (e:EOFError) {
165                         }
166                        
167                         return -1;
168                 }
169                
170                 private function flagSWF9Bit(bytes:ByteArray):void
171                 {
172                         var pos:int = findFileAttributesPosition(getBodyPosition(bytes), bytes);
173                         if (pos != -1) {
174                                 bytes[pos + 2] |= 0x08;
175                         }
176                         else {
177                                 insertFileAttributesTag(bytes);
178                         }
179                 }
180                
181                 private function insertFileAttributesTag(bytes:ByteArray):void
182                 {
183                         var pos:uint = getBodyPosition(bytes);
184                         var afterBytes:ByteArray = new ByteArray();
185                         afterBytes.writeBytes(bytes, pos);
186                         bytes.length = pos;
187                         bytes.position = pos;
188                         bytes.writeByte(0x44);
189                         bytes.writeByte(0x11);
190                         bytes.writeByte(0x08);
191                         bytes.writeByte(0x00);
192                         bytes.writeByte(0x00);
193                         bytes.writeByte(0x00);
194                         bytes.writeBytes(afterBytes);
195                         afterBytes.length = 0;
196                 }
197                
198                 private function updateVersion(bytes:ByteArray, version:uint):void
199                 {
200                         bytes[3] = version;
201                 }
202                
203                 private function ioErrorHandler(event:IOErrorEvent):void
204                 {
205                         loader.contentLoaderInfo.dispatchEvent(event.clone());
206                 }
207                
208                 private function securityErrorHandler(event:SecurityErrorEvent):void
209                 {
210                         loader.contentLoaderInfo.dispatchEvent(event.clone());
211                 }
212         }
213 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。