├── .gitignore
├── LICENSE
├── README.md
├── libs
├── SwfDiy.swc
└── zip.swc
└── src
├── SwfEncryptor-app.xml
├── SwfEncryptor.mxml
├── com
└── domlib
│ ├── encrypt
│ ├── ClassAnalyzer.as
│ ├── ClassInfo.as
│ └── SwfEncrypt.as
│ └── utils
│ ├── ClassUtil.as
│ ├── CodeFilter.as
│ ├── CodeUtil.as
│ ├── FileUtil.as
│ └── StringUtil.as
└── encrypt.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build and Release Folders
2 | bin/
3 | bin-debug/
4 | bin-release/
5 |
6 | # Other files and folders
7 | .settings/
8 |
9 | # Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties`
10 | # should NOT be excluded as they contain compiler settings and other important
11 | # information for Eclipse / Flash Builder.
12 | /*.fxpProperties
13 | /.project
14 | /.flexProperties
15 | /.actionScriptProperties
16 | *.air
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 DOM
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SwfEncryptor
2 | ============
3 |
4 | SWF代码混淆工具
5 |
--------------------------------------------------------------------------------
/libs/SwfDiy.swc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/domchen/SwfEncryptor/0a19dd237fe492a14f01fd0758fa5e1ca900f3f1/libs/SwfDiy.swc
--------------------------------------------------------------------------------
/libs/zip.swc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/domchen/SwfEncryptor/0a19dd237fe492a14f01fd0758fa5e1ca900f3f1/libs/zip.swc
--------------------------------------------------------------------------------
/src/SwfEncryptor-app.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
18 | SwfEncryptor
19 |
20 |
21 | SwfEncryptor
22 |
23 |
25 | SwfEncryptor
26 |
27 |
30 | 1.0.0
31 |
32 |
33 |
34 |
35 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | [此值将由 Flash Builder 在输出 app.xml 中覆盖]
50 |
51 |
52 | SwfEncryptor By DOM - [blog.domlib.com]
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | false
109 | false
110 | false
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
128 |
138 |
139 |
142 |
143 |
144 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
193 |
194 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
--------------------------------------------------------------------------------
/src/SwfEncryptor.mxml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
107 |
108 |
109 |
110 |
111 |
112 |
114 |
115 |
--------------------------------------------------------------------------------
/src/com/domlib/encrypt/ClassAnalyzer.as:
--------------------------------------------------------------------------------
1 | package com.domlib.encrypt
2 | {
3 | import com.domlib.utils.ClassUtil;
4 | import com.domlib.utils.CodeFilter;
5 | import com.domlib.utils.FileUtil;
6 | import com.domlib.utils.StringUtil;
7 |
8 | import flash.events.EventDispatcher;
9 | import flash.filesystem.File;
10 | import flash.utils.Dictionary;
11 |
12 |
13 | /**
14 | * AS3源码分析工具
15 | * @author dom
16 | */
17 | public class ClassAnalyzer extends EventDispatcher
18 | {
19 | public function ClassAnalyzer()
20 | {
21 | super();
22 | }
23 | /**
24 | * 工程源代码路径
25 | */
26 | public var srcPath:String = "";
27 |
28 | /**
29 | * 开始混淆
30 | */
31 | public function startAnalyze(srcPath:String):void
32 | {
33 | if(!srcPath)
34 | return;
35 | this.srcPath = FileUtil.escapePath(srcPath);
36 | analyzeFiles();
37 | }
38 |
39 | /**
40 | * as路径转换为类名
41 | */
42 | public function as2Class(path:String):String
43 | {
44 | path = FileUtil.escapeUrl(path);
45 | var className:String;
46 | className = path.substring(srcPath.length,path.length-3);
47 | className = className.split("/").join(".");
48 | return className;
49 | }
50 | /**
51 | * 类完全限定名转换为as路径
52 | */
53 | public function class2As(className:String):String
54 | {
55 | className = className.split("::").join(".");
56 | className = className.split(".").join("/");
57 | return srcPath+className+".as";
58 | }
59 | /**
60 | * mxml路径转换为类名
61 | */
62 | public function mxml2Class(path:String):String
63 | {
64 | path = FileUtil.escapeUrl(path);
65 | var className:String;
66 | className = path.substring(srcPath.length,path.length-5);
67 | className = className.split("/").join(".");
68 | return className;
69 | }
70 | /**
71 | * 类完全限定名转换为mxml路径
72 | */
73 | public function class2Mxml(className:String):String
74 | {
75 | className = className.split("::").join(".");
76 | className = className.split(".").join("/");
77 | return srcPath+className+".mxml";
78 | }
79 |
80 | /**
81 | * as文件列表
82 | */
83 | private var classInfoList:Vector. = new Vector.();
84 |
85 | private var classInfoDic:Dictionary = new Dictionary();
86 | /**
87 | * 获取包名列表
88 | */
89 | public function get getPackageList():Array
90 | {
91 | var list:Array = [];
92 | for each(var info:ClassInfo in classInfoList)
93 | {
94 | if(info.packageName&&list.indexOf(info.packageName)==-1)
95 | list.push(info.packageName);
96 | }
97 | return list;
98 | }
99 | /**
100 | * 获取关键字列表
101 | */
102 | public function get keyList():Array
103 | {
104 | var list:Array = [];
105 | var key:String;
106 | for each(var info:ClassInfo in classInfoList)
107 | {
108 | key = info.className;
109 | if(key&&list.indexOf(key)==-1)
110 | list.push(key);
111 | for each(key in info.privateVars)
112 | {
113 | if(key&&list.indexOf(key)==-1)
114 | list.push(key);
115 | }
116 | for each(key in info.privateFuncs)
117 | {
118 | if(key&&list.indexOf(key)==-1)
119 | list.push(key);
120 | }
121 | for each(key in info.publicVars)
122 | {
123 | if(key&&list.indexOf(key)==-1)
124 | list.push(key);
125 | }
126 | for each(key in info.publicFuncs)
127 | {
128 | if(key&&list.indexOf(key)==-1)
129 | list.push(key);
130 | }
131 | }
132 | return list;
133 | }
134 | /**
135 | * 分析文件
136 | */
137 | private function analyzeFiles():void
138 | {
139 | classInfoList = new Vector.();
140 | classInfoDic = new Dictionary();
141 | FileUtil.search(srcPath,null,filterFunc);
142 | }
143 |
144 | private function filterFunc(file:File):Boolean
145 | {
146 | if(file.isDirectory)
147 | {
148 | if(file.name.charAt(0)!=".")
149 | return true;
150 | }
151 | else if(file.extension)
152 | {
153 | var ext:String = file.extension.toLowerCase();
154 | if(ext=="as")
155 | analyzeAS(FileUtil.escapeUrl(file.nativePath));
156 | else if(ext=="mxml")
157 | analyzeMXML(FileUtil.escapeUrl(file.nativePath));
158 | }
159 | return false;
160 | }
161 |
162 | /**
163 | * 解析一个mxml文件
164 | */
165 | private function analyzeMXML(path:String):void
166 | {
167 | if(classInfoDic[path])
168 | return;
169 | var info:ClassInfo = new ClassInfo();
170 | classInfoDic[path] = info;
171 | info.type = "mxml";
172 | info.filePath = path;
173 | var className:String = mxml2Class(path);
174 | info.className = ClassUtil.getID(className);
175 | info.packageName = ClassUtil.getPackage(className);
176 | var mxmlText:String = FileUtil.openAsString(path);
177 | mxmlText = mxmlText.split("\r\n").join("\n").split("\r").join("\n");
178 | var xml:XML;
179 | try
180 | {
181 | xml = new XML(mxmlText);
182 | }
183 | catch(e:Error)
184 | {
185 | }
186 | if(xml)
187 | {
188 | var ns:Namespace = xml.namespace();
189 | if(!isDefaultNs(ns))
190 | {
191 | var superClass:String = ns.uri;
192 | info.superClass = superClass.substring(0,superClass.length-1)+xml.localName();
193 | }
194 |
195 | if(xml.hasOwnProperty("@implements"))
196 | {
197 | var implStr:String = xml["@implements"];
198 | var implStrs:Array = implStr.split(",");
199 | for each(var impl:String in implStrs)
200 | {
201 | impl = StringUtil.trim(impl);
202 | if(impl)
203 | info.implementsList.push(impl);
204 | }
205 | }
206 |
207 | var fx:Namespace = new Namespace("fx","http://ns.adobe.com/mxml/2009");
208 | var script:XML = xml.fx::Script[0];
209 | if(script)
210 | {
211 | var asText:String = script.toString();
212 | var index:int = asText.lastIndexOf("import ");
213 | if(index!=-1)
214 | {
215 | var tailStr:String = asText.substr(index);
216 | var i:int = tailStr.indexOf(";");
217 | var j:int = tailStr.indexOf("\n");
218 | if(j!=-1&&i!=-1&&j0)
336 | {
337 | if(impStr.charAt(impStr.length-1)==";")
338 | impStr = impStr.substr(0,impStr.length-1);
339 | else
340 | break;
341 | }
342 | info.importList.push(impStr);
343 | }
344 | }
345 | }
346 | /**
347 | * 获取变量和函数名列表
348 | */
349 | private function getVarsAndFuncs(asText:String,info:ClassInfo):void
350 | {
351 | var closed:Boolean = true;
352 | var index:int;
353 | var indent:int = 2;
354 | while(asText.length>0)
355 | {
356 | var contentText:String = "";
357 | index = asText.indexOf("{");
358 | var i:int = asText.indexOf("}");
359 | if(index!=-1&&(i==-1||i>index))
360 | {
361 | if(indent==2)
362 | contentText = asText.substr(0,index);
363 | asText = asText.substr(index+1);
364 | indent++;
365 | }
366 | else if(i!=-1)
367 | {
368 | if(indent==2)
369 | contentText = asText.substr(0,i);
370 | asText = asText.substr(i+1);
371 | indent--;
372 | }
373 | else
374 | {
375 | contentText = asText;
376 | asText = "";
377 | }
378 | if(contentText)
379 | {
380 | while(contentText.length>0)
381 | {
382 | index = contentText.indexOf("function ");
383 | i = contentText.indexOf("var ");
384 | if(index!=-1&&(i==-1||i>index))
385 | {
386 | var preStr:String = contentText.substr(0,index+9);
387 | contentText = contentText.substr(index+9);
388 | if(preStr.indexOf("override ")!=-1)
389 | continue;
390 | var key:String = getFirstWord(contentText);
391 | if(key=="set"||key=="get")
392 | {
393 | var isGet:Boolean = (key=="get");
394 | index = contentText.indexOf(key);
395 | key = getFirstWord(contentText.substr(index+3));
396 | if(isPrivate(preStr))
397 | {
398 | if(info.privateVars.indexOf(key)==-1)
399 | info.privateVars.push(key);
400 | }
401 | else
402 | {
403 | if(info.publicVars.indexOf(key)==-1)
404 | info.publicVars.push(key);
405 | }
406 | if(isGet)
407 | {
408 | index = contentText.indexOf(")");
409 | contentText = contentText.substr(index+1);
410 | }
411 | index = contentText.indexOf(":");
412 | contentText = contentText.substr(index+1);
413 | var type:String = getFirstWord(contentText);
414 | info.typeDic[key] = getFullClassName(type,info);
415 | }
416 | else if(key)
417 | {
418 | if(isPrivate(preStr))
419 | info.privateFuncs.push(key);
420 | else
421 | info.publicFuncs.push(key);
422 | index = contentText.indexOf(")");
423 | contentText = contentText.substr(index+1);
424 | index = contentText.indexOf(":");
425 | contentText = contentText.substr(index+1);
426 | type = getFirstWord(contentText);
427 | info.typeDic[key] = getFullClassName(type,info);
428 | }
429 | }
430 | else if(i!=-1)
431 | {
432 | index = contentText.indexOf("var ");
433 | preStr = contentText.substr(0,index+4);
434 | contentText = contentText.substr(index+4);
435 | key = getFirstWord(contentText);
436 | if(key)
437 | {
438 | if(isPrivate(preStr))
439 | info.privateVars.push(key);
440 | else
441 | info.publicVars.push(key);
442 | index = contentText.indexOf(":");
443 | contentText = contentText.substr(index+1);
444 | type = getFirstWord(contentText);
445 | info.typeDic[key] = getFullClassName(type,info);
446 | }
447 | }
448 | else
449 | {
450 | break;
451 | }
452 | }
453 | }
454 | }
455 | }
456 |
457 | /**
458 | * 是否含有private
459 | */
460 | private function isPrivate(str:String):Boolean
461 | {
462 | var i:int = str.lastIndexOf("private");
463 | var j:int = str.lastIndexOf("public");
464 | var k:int = str.lastIndexOf("protected");
465 | if(i>j&&i>k)
466 | return true;
467 | return false;
468 | }
469 | /**
470 | * 获取完整的类名
471 | */
472 | private function getFullClassName(className:String,info:ClassInfo):String
473 | {
474 | if(className.indexOf(".")!=-1)
475 | return className;
476 | var found:Boolean = false;
477 | for each(var classStr:String in info.importList)
478 | {
479 | if(ClassUtil.getID(classStr)==className)
480 | {
481 | found = true;
482 | className = classStr;
483 | break;
484 | }
485 | }
486 | if(!found&&info.packageName)
487 | {
488 | var full:String = info.packageName+"."+className;
489 | if(FileUtil.exists(class2As(full))||FileUtil.exists(class2Mxml(full)))
490 | className = full;
491 | }
492 | return className;
493 | }
494 |
495 | /**
496 | * 获取第一个词组字符串
497 | */
498 | public static function getFirstWord(str:String):String
499 | {
500 | str = StringUtil.trimLeft(str);
501 | var length:int = str.length;
502 | var index:int = 0;
503 | while(index"9")&&(char<"a"||char>"z")&&(char<"A"||char>"Z"))
507 | {
508 | break;
509 | }
510 | index++;
511 | }
512 | return str.substr(0,index);
513 | }
514 | }
515 | }
--------------------------------------------------------------------------------
/src/com/domlib/encrypt/ClassInfo.as:
--------------------------------------------------------------------------------
1 | package com.domlib.encrypt
2 | {
3 | import flash.utils.Dictionary;
4 |
5 | /**
6 | * 类属性
7 | * @author dom
8 | */
9 | public class ClassInfo
10 | {
11 | public function ClassInfo()
12 | {
13 | }
14 | /**
15 | * 类型:as,mxml
16 | */
17 | public var type:String = "as";
18 | /**
19 | * 文件路径
20 | */
21 | public var filePath:String = "";
22 | /**
23 | * 类名
24 | */
25 | public var className:String = "";
26 | /**
27 | * 包名
28 | */
29 | public var packageName:String = "";
30 | /**
31 | * 父级类名
32 | */
33 | public var superClass:String = "";
34 | /**
35 | * 导入的包列表
36 | */
37 | public var importList:Vector. = new Vector.();
38 | /**
39 | * 实现的接口列表
40 | */
41 | public var implementsList:Vector. = new Vector.();
42 | /**
43 | * 私有变量名列表
44 | */
45 | public var privateVars:Vector. = new Vector.();
46 | /**
47 | * 公开变量名列表
48 | */
49 | public var publicVars:Vector. = new Vector.();
50 | /**
51 | * 私有函数名列表
52 | */
53 | public var privateFuncs:Vector. = new Vector.();
54 | /**
55 | * 公开函数名列表
56 | */
57 | public var publicFuncs:Vector. = new Vector.();
58 | /**
59 | * 变量和函数名对应的值类型
60 | */
61 | public var typeDic:Dictionary = new Dictionary();
62 |
63 | }
64 | }
--------------------------------------------------------------------------------
/src/com/domlib/encrypt/SwfEncrypt.as:
--------------------------------------------------------------------------------
1 | package com.domlib.encrypt
2 | {
3 | import com.domlib.utils.CodeUtil;
4 | import com.domlib.utils.FileUtil;
5 | import com.domlib.utils.StringUtil;
6 | import com.swfdiy.data.ABC;
7 | import com.swfdiy.data.SWF;
8 | import com.swfdiy.data.SWFTag;
9 | import com.swfdiy.data.SWFTag.TagDoABC;
10 |
11 | import flash.events.EventDispatcher;
12 | import flash.filesystem.File;
13 | import flash.utils.ByteArray;
14 | import flash.utils.Dictionary;
15 |
16 | import nochump.util.zip.ZipEntry;
17 | import nochump.util.zip.ZipFile;
18 |
19 |
20 | /**
21 | * SWF混淆工具
22 | * @author dom
23 | */
24 | public class SwfEncrypt extends EventDispatcher
25 | {
26 | public function SwfEncrypt()
27 | {
28 | super();
29 | }
30 |
31 | /**
32 | * 要排除的关键字
33 | */
34 | private var excludeDic:Dictionary = new Dictionary();
35 | /**
36 | * 包路径字典
37 | */
38 | private var packageDic:Dictionary = new Dictionary();
39 | /**
40 | * 要混淆的关键字列表
41 | */
42 | private var keyList:Array = [];
43 | /**
44 | * 要混淆的包名列表
45 | */
46 | private var packageList:Array = [];
47 | /**
48 | * 目标项目路径
49 | */
50 | private var targetSrc:String = "";
51 |
52 | private var dirNames:Object = {};
53 | /**
54 | * 开始混淆
55 | * @param srcPaths 要混淆的src源码路径列表
56 | * @param excludeSwfs 要排除关键字的外部swf/swc路径列表
57 | * @param targetSrc 要发布到的src路径列表
58 | * @param keyWordPath 可选,载入上一次使用的关键字映射表,若有增加,则同时写入。
59 | */
60 | public function startMixUp(srcPaths:Array,excludeSwfs:Array,
61 | targetSrc:String,keyWordPath:String="",excludeKeys:Array = null):void
62 | {
63 | excludeDic = new Dictionary();
64 | packageDic = new Dictionary();
65 | keyList = [];
66 | packageList = [];
67 | targetSrc = new File(targetSrc).nativePath;
68 | targetSrc = FileUtil.escapeUrl(targetSrc)+"/";
69 | this.targetSrc = targetSrc;
70 |
71 | var list:Array = [];
72 | dirNames = {};
73 | for each(var srcPath:String in srcPaths)
74 | {
75 | FileUtil.search(srcPath,null,dirFilterFunc);
76 | list = list.concat(FileUtil.search(srcPath,""));
77 | }
78 | for each(var file:File in list)
79 | {
80 | if(file.isDirectory)
81 | continue;
82 | if(file.parent.name=="src" || !file.extension || ( extensions.indexOf(file.extension.toLowerCase())<0 ))
83 | {
84 | var name:String = FileUtil.getFileName(file.nativePath);
85 | excludeDic[name] = true;
86 | }
87 | if(!file.extension || ( extensions.indexOf(file.extension.toLowerCase())<0 ))
88 | continue;
89 | if(file.extension.toLowerCase()=="as")
90 | {
91 | var text:String = FileUtil.openAsString(file.nativePath);
92 | checkAsFile(text);
93 | }
94 | else
95 | {
96 | try
97 | {
98 | var xmlStr:String = FileUtil.openAsString(file.nativePath);
99 | var xml:XML = new XML(xmlStr);
100 | checkXmlFile(xml);
101 | }
102 | catch(e:Error){}
103 | }
104 | }
105 |
106 | readKeyFromExcludeSwf(excludeSwfs);
107 | if(excludeKeys != null)
108 | {
109 | readKeyFromExcludeKeys(excludeKeys);
110 | }
111 | var analyzer:ClassAnalyzer = new ClassAnalyzer();
112 | for each(var path:String in srcPaths)
113 | {
114 | analyzer.startAnalyze(path);
115 | list = analyzer.getPackageList;
116 | for each(var key:String in list)
117 | {
118 | if(propList.indexOf(key)!=-1)
119 | continue;
120 | packageDic[key] = true;
121 | if(excludeDic[key]===undefined&&isNaN(Number(key)))
122 | {
123 | var prefix:String = getPrefix(key);
124 | if(excludeDic[prefix]===undefined)
125 | {
126 | if(packageList.indexOf(key)==-1)
127 | packageList.push(key);
128 | }
129 | }
130 | }
131 | list = analyzer.keyList;
132 | for each(key in list)
133 | {
134 | if(propList.indexOf(key)!=-1)
135 | continue;
136 | if(excludeDic[key]===undefined&&isNaN(Number(key)))
137 | {
138 | prefix = getPrefix(key);
139 | if(excludeDic[prefix]===undefined)
140 | {
141 | if(keyList.indexOf(key)==-1)
142 | keyList.push(key);
143 | }
144 | }
145 | }
146 | }
147 | for(var i:int=keyList.length-1;i>=0;i--)
148 | {
149 | key = keyList[i];
150 | if(dirNames[key])
151 | {
152 | keyList.splice(i,1);
153 | }
154 | else
155 | {
156 | for(var p:String in packageDic)
157 | {
158 | var index:int = p.indexOf(key);
159 | if(index!=-1&&isFullWord(p,index,index+key.length))
160 | {
161 | keyList.splice(i,1);
162 | break;
163 | }
164 | }
165 | }
166 | }
167 |
168 | generateFiles(srcPaths,keyWordPath);
169 | }
170 |
171 | private function dirFilterFunc(file:File):Boolean
172 | {
173 | if(file.isDirectory&&file.name.charAt(0)!=".")
174 | {
175 | dirNames[file.name] = true;
176 | return true;
177 | }
178 | return false;
179 | }
180 |
181 | //搜索的扩展名
182 | private var extensions:Vector. = new ["as","xml","mxml"];
183 | //搜索回调函数
184 | private function filterFunc(file:File):Boolean
185 | {
186 | if(file.isDirectory)
187 | {
188 | if(file.name.charAt(0)!=".")
189 | return true;
190 | }
191 | else if(file.extension&&extensions.indexOf(file.extension)!=-1)
192 | {
193 | return true;
194 | }
195 | return false;
196 | }
197 |
198 | /**
199 | * Dictionary自身的关键字列表
200 | */
201 | private var propList:Vector. =
202 | new ["hasOwnProperty","isPrototypeOf","valueOf",
203 | "propertyIsEnumerable","setPropertyIsEnumerable","toString"];
204 |
205 | /**
206 | * 获取as文件内的关键字
207 | */
208 | private function checkAsFile(data:String):void
209 | {
210 | var lines:Array = data.split("\n");
211 | var length:int = lines.length;
212 | var strLen:int;
213 | var line:String;
214 | var charCode:Number;
215 | var isNoteStart:Boolean = false;
216 | var index:int;
217 | var k:int;
218 | var noteStart:String = "/**";
219 | var noteEnd:String = "*/";
220 |
221 | for(var i:int=0;i0)
382 | {
383 | var char:String = key.charAt(index);
384 | if(char>="0"&&char<="9")
385 | {
386 | index--;
387 | }
388 | else
389 | {
390 | break;
391 | }
392 | }
393 | return key.substring(0,index+1);
394 | }
395 |
396 |
397 | private var fxNs:Namespace = new Namespace("fx","http://ns.adobe.com/mxml/2009");
398 | /**
399 | * 获取xml文件内的关键字
400 | */
401 | private function checkXmlFile(xml:XML):void
402 | {
403 | var key:String = xml.localName();
404 | if(key=="Script"&&xml.namespace()==fxNs)
405 | {
406 | checkAsFile(xml.toString());
407 | return;
408 | }
409 | if(isNaN(Number(key)))
410 | {
411 | excludeDic[key] = true;
412 | }
413 | for each(var attrib:XML in xml.attributes())
414 | {
415 | key = attrib.toString();
416 | var varList:Array = getVariables(key);
417 | for each(key in varList)
418 | {
419 | if(isNaN(Number(key)))
420 | {
421 | excludeDic[key] = true;
422 | }
423 | }
424 |
425 | key = attrib.localName();
426 | if(isNaN(Number(key)))
427 | {
428 | excludeDic[key] = true;
429 | }
430 | }
431 |
432 | for each(var item:XML in xml.children())
433 | {
434 | checkXmlFile(item);
435 | }
436 | }
437 |
438 | /**
439 | * 获取变量关键字列表
440 | */
441 | private function getVariables(codeText:String):Array
442 | {
443 | var list:Array = [];
444 | var word:String = "";
445 | var start:Boolean = false;
446 | var char:String = "";
447 | var lastChar:String = " ";
448 | while(codeText.length>0)
449 | {
450 | char = codeText.charAt(0);
451 | codeText = codeText.substring(1);
452 | if(start)
453 | {
454 | if(CodeUtil.isVariableChar(char))
455 | {
456 | word += char;
457 | }
458 | else
459 | {
460 | if(list.indexOf(word)==-1)
461 | {
462 | list.push(word);
463 | }
464 | word = "";
465 | start = false;
466 | }
467 | }
468 | else
469 | {
470 | if(CodeUtil.isVariableChar(char))
471 | {
472 | word = char;
473 | start = true;
474 | }
475 | }
476 | lastChar = char;
477 | }
478 | if(word)
479 | {
480 | if(list.indexOf(word)==-1)
481 | {
482 | list.push(word);
483 | }
484 | }
485 | return list;
486 | }
487 |
488 | /**
489 | * 生成混淆后的源码
490 | */
491 | private function generateFiles(srcPaths:Array,keyWordPath:String):void
492 | {
493 | var keyBytes:ByteArray = FileUtil.openAsByteArray(keyWordPath);
494 | try
495 | {
496 | keyObject = keyBytes.readObject();
497 | for(var key:String in keyObject)
498 | {
499 | count++;
500 | }
501 | }
502 | catch(e:Error)
503 | {
504 | keyObject = {};
505 | }
506 | var fileList:Array = [];
507 | for each(var srcPath:String in srcPaths)
508 | {
509 | srcPath = new File(srcPath).nativePath;
510 | srcPath = FileUtil.escapeUrl(srcPath)+"/";
511 | var list:Array = FileUtil.search(srcPath,null,filterFunc2);
512 | for each(var file:File in list)
513 | {
514 | var ext:String = file.extension.toLowerCase();
515 | var targetPath:String = replaceSrc(file.nativePath,srcPath,targetSrc);
516 | if(ext=="as"||ext=="mxml")
517 | {
518 | var p:String = getPackage(file.nativePath);
519 | var name:String = FileUtil.getFileName(file.nativePath);
520 | if(keyList.indexOf(name)!=-1)
521 | {
522 | name = getKey(name);
523 | }
524 | if(packageList.indexOf(p)!=-1)
525 | {
526 | p = getKey(p);
527 | }
528 | p = p.split(".").join("/");
529 | targetPath = targetSrc+p+"/"+name+"."+file.extension;
530 | fileList.push(targetPath);
531 | }
532 | if(ext=="xml"||ext=="css")
533 | {
534 | fileList.push(targetPath);
535 | }
536 | FileUtil.copyTo(file.nativePath,targetPath,true);
537 | }
538 | }
539 | packageList.sort(sortOnLength);
540 | keyList.sort(sortOnLength);
541 | for each(var path:String in fileList)
542 | {
543 | var text:String = FileUtil.openAsString(path);
544 | for each(p in packageList)
545 | {
546 | text = replaceKeyWord(text,p,true);
547 | }
548 | for each(key in keyList)
549 | {
550 | text = replaceKeyWord(text,key);
551 | }
552 | FileUtil.save(path,text);
553 | }
554 |
555 | if(keyWordPath)
556 | {
557 | keyBytes = new ByteArray();
558 | keyBytes.writeObject(keyObject);
559 | FileUtil.save(keyWordPath,keyBytes);
560 | }
561 | }
562 |
563 | private function sortOnLength(strA:String,strB:String):int
564 | {
565 | return strB.length-strA.length;
566 | }
567 | /**
568 | * 替换文本中出现的关键字
569 | */
570 | private function replaceKeyWord(text:String,key:String,isPackage:Boolean=false):String
571 | {
572 | var index:int = text.indexOf(key);
573 | var returnStr:String = "";
574 | while(index!=-1)
575 | {
576 | returnStr += text.substr(0,index);
577 | if(isFullWord(text,index,index+key.length,isPackage))
578 | {
579 | returnStr += getKey(key);
580 | }
581 | else
582 | {
583 | returnStr += key;
584 | }
585 | text = text.substr(index+key.length);
586 | index = text.indexOf(key);
587 | }
588 | returnStr += text;
589 | return returnStr;
590 | }
591 | /**
592 | * 检查这个字符串是不是一个完整词组
593 | */
594 | private function isFullWord(text:String,startIndex:int,
595 | endIndex:int,isPackage:Boolean=false):Boolean
596 | {
597 | startIndex--;
598 | var char:String = text.charAt(startIndex);
599 | if(char=="_"||char=="$"||(char>="0"&&char<="9")||(char>="a"&&char<="z")||(char>="A"&&char<="Z"))
600 | {
601 | return false;
602 | }
603 | else if(isPackage&&char==".")
604 | {
605 | return false;
606 | }
607 | char = text.charAt(endIndex);
608 | if(isPackage)
609 | {
610 | if(char==".")
611 | {
612 | var str:String = text.substring(0,startIndex);
613 | str = StringUtil.trimRight(str);
614 | if(str.substr(str.length-7,7)=="package")
615 | return false;
616 | str = text.substring(endIndex+1);
617 | str = ClassAnalyzer.getFirstWord(str);
618 | if(keyList.indexOf(str)!=-1)
619 | return true;
620 | var p:String = text.substring(startIndex+1,endIndex);
621 | p = getKey(p)+"."+str;
622 | if(FileUtil.exists(class2As(p))||FileUtil.exists(class2Mxml(p)))
623 | return true;
624 | var length:int = text.length;
625 | endIndex++;
626 | while(endIndex="0"&&char<="9")||(char>="a"&&char<="z")||(char>="A"&&char<="Z"));
661 | }
662 |
663 | /**
664 | * 类完全限定名转换为as路径
665 | */
666 | public function class2As(className:String):String
667 | {
668 | className = className.split("::").join(".");
669 | className = className.split(".").join("/");
670 | return targetSrc+className+".as";
671 | }
672 | /**
673 | * 类完全限定名转换为mxml路径
674 | */
675 | public function class2Mxml(className:String):String
676 | {
677 | className = className.split("::").join(".");
678 | className = className.split(".").join("/");
679 | return targetSrc+className+".mxml";
680 | }
681 |
682 | /**
683 | * 混淆字典
684 | */
685 | private var keyObject:Object = {};
686 | /**
687 | * 混淆关键字计数
688 | */
689 | private var count:int = 0;
690 | /**
691 | * 生成混淆字符串
692 | */
693 | private function getKey(key:String):String
694 | {
695 | if(!keyObject[key])
696 | {
697 | count++;
698 | keyObject[key] = "_"+count;
699 | }
700 | return keyObject[key];
701 | }
702 | /**
703 | * 把路径转换为包名
704 | */
705 | private function getPackage(path:String):String
706 | {
707 | path = FileUtil.getDirectory(path);
708 | var index:int = path.lastIndexOf("/src/");
709 | if(index==-1)
710 | {
711 | return path;
712 | }
713 | path = path.substring(index+5,path.length-1);
714 | return path.split("/").join(".");
715 | }
716 | /**
717 | * 替换src路径
718 | */
719 | private function replaceSrc(path:String,source:String,dest:String):String
720 | {
721 | path = FileUtil.escapeUrl(path);
722 | return dest+path.substr(source.length);
723 | }
724 | /**
725 | * 文件搜索回调函数
726 | */
727 | private function filterFunc2(file:File):Boolean
728 | {
729 | if(file.isDirectory)
730 | {
731 | if(file.name.charAt(0)!=".")
732 | return true;
733 | }
734 | else if(file.extension)
735 | {
736 | return true;
737 | }
738 | return false;
739 | }
740 | }
741 | }
742 |
--------------------------------------------------------------------------------
/src/com/domlib/utils/ClassUtil.as:
--------------------------------------------------------------------------------
1 | package com.domlib.utils
2 | {
3 |
4 | /**
5 | * 类名工具
6 | * @author dom
7 | */
8 | public class ClassUtil
9 | {
10 | /**
11 | * 获取类的短名
12 | */
13 | public static function getID(className:String):String
14 | {
15 | if(!className)
16 | return className;
17 | className = className.split("::").join(".");
18 | var index:int = className.lastIndexOf(".");
19 | if(index==-1)
20 | return className;
21 | return className.substring(index+1);
22 | }
23 | /**
24 | * 获取包名
25 | */
26 | public static function getPackage(className:String):String
27 | {
28 | if(!className)
29 | return "";
30 | className = className.split("::").join(".");
31 | var index:int = className.lastIndexOf(".");
32 | if(index==-1)
33 | return "";
34 | return className.substring(0,index);
35 | }
36 | /**
37 | * 根据包名和类短名获取完整类名
38 | */
39 | public static function getClassName(packageName:String,id:String):String
40 | {
41 | if(!packageName)
42 | return id;
43 | return packageName+"."+id;
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/com/domlib/utils/CodeFilter.as:
--------------------------------------------------------------------------------
1 | package com.domlib.utils
2 | {
3 | /**
4 | * 过滤代码中的所有常量和注释内容的工具类
5 | * @author dom
6 | */
7 | public class CodeFilter
8 | {
9 | /**
10 | * 构造函数
11 | */
12 | public function CodeFilter()
13 | {
14 | }
15 |
16 | /**
17 | * 是否为占位符
18 | */
19 | public static function isNBSP(str:String):Boolean
20 | {
21 | if(!str||str.length<3)
22 | return false;
23 | return str.charAt(0)=="\v"&&str.charAt(str.length-1)=="\v";
24 | }
25 | /**
26 | * 获取文本末尾的占位符。若最后一个字符不是占位符。返回""
27 | */
28 | public static function getLastNBSP(str:String):String
29 | {
30 | if(!str||str.length<3||str.charAt(str.length-1)!="\v")
31 | return "";
32 | str = str.substring(0,str.length-1);
33 | var index:int = str.lastIndexOf("\v");
34 | if(index==-1)
35 | return "";
36 | var char:String = str.substring(index+1);
37 | if(isNaN(parseInt(char)))
38 | return "";
39 | return str.substring(index)+"\v";
40 | }
41 | /**
42 | * 获取文本末尾的占位符。若最后一个字符不是占位符。返回""
43 | */
44 | public static function getFirstNBSP(str:String):String
45 | {
46 | if(!str||str.length<3||str.charAt(0)!="\v")
47 | return "";
48 | str = str.substring(1);
49 | var index:int = str.indexOf("\v");
50 | if(index==-1)
51 | return "";
52 | var char:String = str.substring(0,index);
53 | if(isNaN(parseInt(char)))
54 | return "";
55 | return "\v"+str.substring(0,index+1);
56 | }
57 |
58 | private function getCommentIndex(str:String):int
59 | {
60 | return parseInt(str.substring(1,str.length-1));
61 | }
62 |
63 | private var nbsp:String = null;
64 | /**
65 | * 获取占位符
66 | */
67 | private function getNBSP():String
68 | {
69 | if(nbsp!==null)
70 | return nbsp;
71 | return "\v"+commentLines.length+"\v";
72 | }
73 | /**
74 | * 注释行
75 | */
76 | private var commentLines:Array = [];
77 | /**
78 | * 移除代码注释和字符串常量
79 | */
80 | public function removeComment(codeText:String,nbsp:String=null):String
81 | {
82 | this.nbsp = nbsp;
83 | var trimText:String = "";
84 | codeText = codeText.split("\\\\").join("\v-0\v");
85 | codeText = codeText.split("\\\"").join("\v-1\v");
86 | codeText = codeText.split("\\\'").join("\v-2\v");
87 | codeText = codeText.split("\r\n").join("\n").split("\r").join("\n");
88 | commentLines = [];
89 | while(codeText.length>0)
90 | {
91 | var quoteIndex:int = codeText.indexOf("\"");
92 | if(quoteIndex==-1)
93 | quoteIndex = int.MAX_VALUE;
94 | var squoteIndex:int = codeText.indexOf("'");
95 | if(squoteIndex==-1)
96 | squoteIndex = int.MAX_VALUE;
97 | var commentIndex:int = codeText.indexOf("/*");
98 | if(commentIndex==-1)
99 | commentIndex = int.MAX_VALUE;
100 | var lineCommonentIndex:int = codeText.indexOf("//");
101 | if(lineCommonentIndex==-1)
102 | lineCommonentIndex = int.MAX_VALUE;
103 | var index:int = Math.min(quoteIndex,squoteIndex,commentIndex,lineCommonentIndex);
104 | if(index==int.MAX_VALUE)
105 | {
106 | trimText += codeText;
107 | break;
108 | }
109 | trimText += codeText.substring(0,index)+getNBSP();
110 | codeText = codeText.substring(index);
111 | switch(index)
112 | {
113 | case quoteIndex:
114 | codeText = codeText.substring(1);
115 | index = codeText.indexOf("\"");
116 | if(index==-1)
117 | index = codeText.length-1;
118 | commentLines.push("\""+codeText.substring(0,index+1));
119 | codeText = codeText.substring(index+1);
120 | break;
121 | case squoteIndex:
122 | codeText = codeText.substring(1);
123 | index = codeText.indexOf("'");
124 | if(index==-1)
125 | index=codeText.length-1;
126 | commentLines.push("'"+codeText.substring(0,index+1));
127 | codeText = codeText.substring(index+1);
128 | break;
129 | case commentIndex:
130 | index = codeText.indexOf("*/");
131 | if(index==-1)
132 | index=codeText.length-1;
133 | commentLines.push(codeText.substring(0,index+2));
134 | codeText = codeText.substring(index+2);
135 | break;
136 | case lineCommonentIndex:
137 | index = codeText.indexOf("\n");
138 | if(index==-1)
139 | index=codeText.length-1;
140 | commentLines.push(codeText.substring(0,index));
141 | codeText = codeText.substring(index);
142 | break;
143 | }
144 | }
145 | codeText = trimText.split("\v-0\v").join("\\\\");
146 | codeText = codeText.split("\v-1\v").join("\\\"");
147 | codeText = codeText.split("\v-2\v").join("\\\'");
148 | var length:int = commentLines.length;
149 | for(var i:int=0;i0)
170 | {
171 | var index:int = changeStr.indexOf("\v");
172 | if(index==-1)
173 | {
174 | break;
175 | }
176 | changeStr = changeStr.substring(index);
177 | var str:String = getFirstNBSP(changeStr)
178 | if(str)
179 | {
180 | changeStr = changeStr.substring(str.length);
181 | index = getCommentIndex(str);
182 | if(numIndent>0)
183 | {
184 | commentLines[index] = CodeUtil.addIndent(commentLines[index],numIndent,true);
185 | }
186 | else
187 | {
188 | commentLines[index] = CodeUtil.removeIndent(commentLines[index],-numIndent);
189 | }
190 | }
191 | else
192 | {
193 | changeStr = changeStr.substring(1);
194 | }
195 | }
196 | }
197 | /**
198 | * 回复注释行
199 | */
200 | public function recoveryComment(codeText:String):String
201 | {
202 | if(!codeText)
203 | return codeText;
204 | var constArray:Array = this.commentLines.concat();
205 | var tsText:String = "";
206 | while(codeText.length>0)
207 | {
208 | var index:int = codeText.indexOf("\v");
209 | if(index==-1)
210 | {
211 | tsText += codeText;
212 | break;
213 | }
214 | tsText += codeText.substring(0,index);
215 | codeText = codeText.substring(index);
216 | var str:String = getFirstNBSP(codeText);
217 | if(str)
218 | {
219 | index = getCommentIndex(str);
220 | tsText += constArray[index];
221 | codeText = codeText.substring(str.length);
222 | }
223 | else
224 | {
225 | tsText += "\v";
226 | codeText = codeText.substring(1)
227 | }
228 | }
229 | return tsText;
230 | }
231 | }
232 | }
--------------------------------------------------------------------------------
/src/com/domlib/utils/CodeUtil.as:
--------------------------------------------------------------------------------
1 | package com.domlib.utils
2 | {
3 |
4 | /**
5 | * 代码解析工具类
6 | * @author dom
7 | */
8 | public class CodeUtil
9 | {
10 | /**
11 | * 删除每行多余的缩进。
12 | * @param codeText 要处理的代码字符串
13 | * @param numIndent 每行要删除的缩进数量。默认删除一个\t或一个空白
14 | */
15 | public static function removeIndent(codeText:String,numIndent:int=1):String
16 | {
17 | var lines:Array = codeText.split("\n");
18 | for(var i:int=lines.length-1;i>=0;i--)
19 | {
20 | var line:String = lines[i];
21 | var count:int = numIndent;
22 | while(count>0)
23 | {
24 | var char:String = line.charAt(0);
25 | if(char=="\t")
26 | {
27 | line = line.substring(1);
28 | }
29 | else if(char==" ")
30 | {
31 | var index:int = 4;
32 | while(index>0)
33 | {
34 | if(line.charAt(0)==" ")
35 | line = line.substring(1);
36 | index--;
37 | }
38 |
39 | }
40 | count--;
41 | }
42 | lines[i] = line;
43 |
44 | }
45 | codeText = lines.join("\n");
46 | return codeText;
47 | }
48 | /**
49 | * 每行增加相同数量缩进。
50 | * @param codeText 要处理的代码字符串
51 | * @param numIndent 要增加的缩进数量,使用\t字符
52 | * @param ignoreFirstLine 是否忽略第一行,默认false。
53 | */
54 | public static function addIndent(codeText:String,numIndent:int=1,ignoreFirstLine:Boolean=false):String
55 | {
56 | var lines:Array = codeText.split("\n");
57 | for(var i:int=lines.length-1;i>=0;i--)
58 | {
59 | if(i==0&&ignoreFirstLine)
60 | continue;
61 | var line:String = lines[i];
62 | var count:int = numIndent;
63 | while(count>0)
64 | {
65 | line = "\t"+line;
66 | count--;
67 | }
68 | lines[i] = line;
69 | }
70 | codeText = lines.join("\n");
71 | return codeText;
72 | }
73 | /**
74 | * 判断一个字符串是否是常量,即全部大写的合法变量。
75 | */
76 | public static function isConstant(word:String):Boolean
77 | {
78 | if(!isVariableWord(word))
79 | return false;
80 | var found:Boolean = false;
81 | for(var i:int=2;i="a"&&char<="z")
85 | {
86 | found = true;
87 | break;
88 | }
89 | }
90 | return !found;
91 | }
92 |
93 | /**
94 | * 判断一个字符串是否为合法变量名,第一个字符为字母,下划线或$开头,第二个字符开始为字母,下划线,数字或$
95 | */
96 | public static function isVariableWord(word:String):Boolean
97 | {
98 | if(!word)
99 | return false;
100 | var char:String = word.charAt(0);
101 | if(!isVariableFirstChar(char))
102 | {
103 | return false;
104 | }
105 | var length:int = word.length;
106 | for(var i:int=1;i="A"||char<="z"&&char>="a"||
122 | char<="9"&&char>="0"||char=="_"||char=="$")
123 | }
124 | /**
125 | * 是否为合法变量字符串的第一个字符,字符为字母,下划线或$
126 | */
127 | public static function isVariableFirstChar(char:String):Boolean
128 | {
129 | return (char<="Z"&&char>="A"||char<="z"&&char>="a"||
130 | char=="_"||char=="$")
131 | }
132 |
133 | /**
134 | * 判断一段代码中是否含有某个变量字符串,且该字符串的前后都不是变量字符。
135 | */
136 | public static function containsVariable(key:String,codeText:String,notProperty:Boolean=false):Boolean
137 | {
138 | var contains:Boolean = false;
139 | while(codeText.length>0)
140 | {
141 | var index:int = codeText.indexOf(key);
142 | if(index==-1)
143 | break;
144 | var lastChar:String = codeText.charAt(index+key.length);
145 | var firstChar:String = codeText.charAt(index-1);
146 | if(!isVariableChar(firstChar)&&!isVariableChar(lastChar)&&
147 | (!notProperty||(firstChar!="."&&firstChar!="@")))
148 | {
149 | contains = true;
150 | break;
151 | }
152 | else
153 | {
154 | codeText = codeText.substring(index+key.length);
155 | }
156 | }
157 | return contains;
158 | }
159 |
160 | /**
161 | * 获取第一个含有key关键字的起始索引,且该关键字的前后都不是变量字符。
162 | */
163 | public static function getFirstVariableIndex(key:String,codeText:String):int{
164 | var subLength:int = 0;
165 | while(codeText.length){
166 | var index:int = codeText.indexOf(key);
167 | if(index==-1){
168 | break;
169 | }
170 | var lastChar:String = codeText.charAt(index+key.length);
171 | var firstChar:String = codeText.charAt(index-1);
172 | if(!isVariableChar(firstChar)&&!isVariableChar(lastChar)){
173 | return subLength+index;
174 | }
175 | else{
176 | subLength += index+key.length;
177 | codeText = codeText.substring(index+key.length);
178 | }
179 | }
180 | return -1;
181 | }
182 | /**
183 | * 获取最后一个含有key关键字的起始索引,且该关键字的前后都不是变量字符。
184 | */
185 | public static function getLastVariableIndex(key:String,codeText:String):int{
186 | while(codeText.length){
187 | var index:int = codeText.lastIndexOf(key);
188 | if(index==-1){
189 | break;
190 | }
191 | var lastChar:String = codeText.charAt(index+key.length);
192 | var firstChar:String = codeText.charAt(index-1);
193 | if(!isVariableChar(firstChar)&&!isVariableChar(lastChar)){
194 | return index;
195 | }
196 | else{
197 | codeText = codeText.substring(0,index);
198 | }
199 | }
200 | return -1;
201 | }
202 |
203 | /**
204 | * 获取第一个词,遇到空白字符或 \n \r \t 后停止。
205 | */
206 | public static function getFirstWord(str:String):String
207 | {
208 | str = StringUtil.trimLeft(str);
209 | var index:int = str.indexOf(" ");
210 | if(index==-1)
211 | index = int.MAX_VALUE;
212 | var rIndex:int = str.indexOf("\r");
213 | if(rIndex==-1)
214 | rIndex = int.MAX_VALUE;
215 | var nIndex:int = str.indexOf("\n");
216 | if(nIndex==-1)
217 | nIndex = int.MAX_VALUE;
218 | var tIndex:int = str.indexOf("\t");
219 | if(tIndex==-1)
220 | tIndex = int.MAX_VALUE;
221 | index = Math.min(index,rIndex,nIndex,tIndex);
222 | str = str.substr(0,index);
223 | return StringUtil.trim(str);
224 | }
225 | /**
226 | * 移除第一个词
227 | * @param str 要处理的字符串
228 | * @param word 要移除的词,若不传入则自动获取。
229 | */
230 | public static function removeFirstWord(str:String,word:String=""):String
231 | {
232 | if(!word)
233 | {
234 | word = getFirstWord(str);
235 | }
236 | var index:int = str.indexOf(word);
237 | if(index==-1)
238 | return str;
239 | return str.substring(index+word.length);
240 | }
241 | /**
242 | * 获取最后一个词,遇到空白字符或 \n \r \t 后停止。
243 | */
244 | public static function getLastWord(str:String):String
245 | {
246 | str = StringUtil.trimRight(str);
247 | var index:int = str.lastIndexOf(" ");
248 | var rIndex:int = str.lastIndexOf("\r");
249 | var nIndex:int = str.lastIndexOf("\n");
250 | var tIndex:int = str.indexOf("\t");
251 | index = Math.max(index,rIndex,nIndex,tIndex);
252 | str = str.substring(index+1);
253 | return StringUtil.trim(str);
254 | }
255 | /**
256 | * 移除最后一个词
257 | * @param str 要处理的字符串
258 | * @param word 要移除的词,若不传入则自动获取。
259 | */
260 | public static function removeLastWord(str:String,word:String=""):String
261 | {
262 | if(!word)
263 | {
264 | word = getLastWord(str);
265 | }
266 | var index:int = str.lastIndexOf(word);
267 | if(index==-1)
268 | return str;
269 | return str.substring(0,index);
270 | }
271 | /**
272 | * 获取字符串起始的第一个变量,返回的字符串两端均没有空白。若第一个非空白字符就不是合法变量字符,则返回空字符串。
273 | */
274 | public static function getFirstVariable(str:String):String
275 | {
276 | str = StringUtil.trimLeft(str);
277 | var word:String = "";
278 | var length:int = str.length;
279 | for(var i:int=0;i=0;i--)
317 | {
318 | var char:String = str.charAt(i);
319 | if(isVariableChar(char))
320 | {
321 | word = char+word;
322 | }
323 | else
324 | {
325 | break;
326 | }
327 | }
328 | return StringUtil.trim(word);
329 | }
330 | /**
331 | * 移除最后一个变量
332 | * @param str 要处理的字符串
333 | * @param word 要移除的变量,若不传入则自动获取。
334 | */
335 | public static function removeLastVariable(str:String,word:String=""):String
336 | {
337 | if(!word)
338 | {
339 | word = getLastVariable(str);
340 | }
341 | var index:int = str.lastIndexOf(word);
342 | if(index==-1)
343 | return str;
344 | return str.substring(0,index);
345 | }
346 | /**
347 | * 获取一对括号的结束点,例如"class A{ function B(){} } class",返回24,若查找失败,返回-1。
348 | */
349 | public static function getBracketEndIndex(codeText:String,left:String="{",right:String="}"):int
350 | {
351 | var indent:int = 0;
352 | var text:String = "";
353 | while(codeText.length>0)
354 | {
355 | var index:int = codeText.indexOf(left);
356 | if(index==-1)
357 | index = int.MAX_VALUE;
358 | var endIndex:int = codeText.indexOf(right);
359 | if(endIndex==-1)
360 | endIndex = int.MAX_VALUE;
361 | index = Math.min(index,endIndex);
362 | if(index==int.MAX_VALUE)
363 | {
364 | return -1;
365 | }
366 | text += codeText.substring(0,index+1);
367 | codeText = codeText.substring(index+1);
368 | if(index==endIndex)
369 | indent--;
370 | else
371 | indent++;
372 | if(indent==0)
373 | {
374 | break;
375 | }
376 | if(codeText.length==0)
377 | return -1;
378 | }
379 | return text.length-1;
380 | }
381 | /**
382 | * 从后往前搜索,获取一对括号的起始点,例如"class A{ function B(){} } class",返回7,若查找失败,返回-1。
383 | */
384 | public static function getBracketStartIndex(codeText:String,left:String="{",right:String="}"):int
385 | {
386 | var indent:int = 0;
387 | while(codeText.length>0)
388 | {
389 | var index:int = codeText.lastIndexOf(left);
390 | var endIndex:int = codeText.lastIndexOf(right);
391 | index = Math.max(index,endIndex);
392 | if(index==-1)
393 | {
394 | return -1;
395 | }
396 | codeText = codeText.substring(0,index);
397 | if(index==endIndex)
398 | indent++;
399 | else
400 | indent--;
401 | if(indent==0)
402 | {
403 | break;
404 | }
405 | if(codeText.length==0)
406 | return -1;
407 | }
408 | return codeText.length;
409 | }
410 |
411 | /**
412 | * 去掉字符串两端所有连续的非变量字符。
413 | * @param str 要格式化的字符串
414 | */
415 | public static function trimVariable(str:String):String
416 | {
417 | return trimVariableLeft(trimVariableRight(str));
418 | }
419 | /**
420 | * 去除字符串左边所有连续的非变量字符。
421 | * @param str 要格式化的字符串
422 | */
423 | public static function trimVariableLeft(str:String):String
424 | {
425 | if(!str)
426 | return "";
427 | var char:String = str.charAt(0);
428 | while(str.length>0&&!isVariableFirstChar(char))
429 | {
430 | str = str.substr(1);
431 | char = str.charAt(0);
432 | }
433 | return str;
434 | }
435 | /**
436 | * 去除字符串右边所有连续的非变量字符。
437 | * @param str 要格式化的字符串
438 | */
439 | public static function trimVariableRight(str:String):String
440 | {
441 | if(!str)
442 | return "";
443 | var char:String = str.charAt(str.length-1);
444 | while(str.length>0&&!isVariableChar(char))
445 | {
446 | str = str.substr(0,str.length-1);
447 | char = str.charAt(str.length-1);
448 | }
449 | return str;
450 | }
451 |
452 | private static var codeFilter:CodeFilter = new CodeFilter();
453 | /**
454 | * 移除代码里的注释和单引号双引号内容
455 | */
456 | public static function removeComment(codeText:String):String
457 | {
458 | return codeFilter.removeComment(codeText,"");
459 | }
460 | }
461 | }
--------------------------------------------------------------------------------
/src/com/domlib/utils/FileUtil.as:
--------------------------------------------------------------------------------
1 | package com.domlib.utils
2 | {
3 | import flash.events.Event;
4 | import flash.events.FileListEvent;
5 | import flash.filesystem.File;
6 | import flash.filesystem.FileMode;
7 | import flash.filesystem.FileStream;
8 | import flash.utils.ByteArray;
9 |
10 | /**
11 | * 常用文件操作方法工具类
12 | * @author dom
13 | */
14 | public class FileUtil
15 | {
16 | /**
17 | * 保存数据到指定文件,返回是否保存成功
18 | * @param path 文件完整路径名
19 | * @param data 要保存的数据
20 | */
21 | public static function save(path:String,data:Object):Boolean
22 | {
23 | path = escapePath(path);
24 | var file:File = new File(File.applicationDirectory.resolvePath(path).nativePath);
25 | if(file.exists)
26 | {//如果存在,先删除,防止出现文件名大小写不能覆盖的问题
27 | deletePath(file.nativePath);
28 | }
29 | if(file.isDirectory)
30 | return false;
31 | var fs:FileStream = new FileStream;
32 | try
33 | {
34 | fs.open(file,FileMode.WRITE);
35 | if(data is ByteArray)
36 | {
37 | fs.writeBytes(data as ByteArray);
38 | }
39 | else if(data is String)
40 | {
41 | fs.writeUTFBytes(data as String);
42 | }
43 | else
44 | {
45 | fs.writeObject(data);
46 | }
47 | }
48 | catch(e:Error)
49 | {
50 | fs.close();
51 | return false;
52 | }
53 | fs.close();
54 | return true;
55 | }
56 |
57 | /**
58 | * 打开文件的简便方法,返回打开的FileStream对象,若打开失败,返回null。
59 | * @param path 要打开的文件路径
60 | */
61 | public static function open(path:String):FileStream
62 | {
63 | path = escapePath(path);
64 | var file:File = new File(File.applicationDirectory.resolvePath(path).nativePath);
65 | var fs:FileStream = new FileStream;
66 | try
67 | {
68 | fs.open(file,FileMode.READ);
69 | }
70 | catch(e:Error)
71 | {
72 | return null;
73 | }
74 | return fs;
75 | }
76 | /**
77 | * 打开文件字节流的简便方法,返回打开的字节流数据,若失败,返回null.
78 | * @param path 要打开的文件路径
79 | */
80 | public static function openAsByteArray(path:String):ByteArray
81 | {
82 | path = escapePath(path);
83 | var fs:FileStream = open(path);
84 | if(!fs)
85 | return null;
86 | fs.position = 0;
87 | var bytes:ByteArray = new ByteArray();
88 | fs.readBytes(bytes);
89 | fs.close();
90 | return bytes;
91 | }
92 | /**
93 | * 打开文本文件的简便方法,返回打开文本的内容,若失败,返回"".
94 | * @param path 要打开的文件路径
95 | */
96 | public static function openAsString(path:String):String
97 | {
98 | path = escapePath(path);
99 | var fs:FileStream = open(path);
100 | if(!fs)
101 | return "";
102 | fs.position = 0;
103 | var content:String = fs.readUTFBytes(fs.bytesAvailable);
104 | fs.close();
105 | return content;
106 | }
107 |
108 | /**
109 | * 打开浏览文件对话框
110 | * @param onSelect 回调函数:单个文件或单个目录:onSelect(file:File);多个文件:onSelect(fileList:Array)
111 | * @param type 浏览类型:1:选择单个文件,2:选择多个文件,3:选择目录
112 | * @param typeFilter 文件类型过滤数组
113 | * @param title 对话框标题
114 | * @param defaultPath 默认路径
115 | */
116 | public static function browseForOpen(onSelect:Function,type:int=1,typeFilter:Array=null,title:String="浏览文件",defaultPath:String=""):void
117 | {
118 | defaultPath = escapePath(defaultPath);
119 | var file:File;
120 | if(defaultPath=="")
121 | file = new File;
122 | else
123 | file = File.applicationDirectory.resolvePath(defaultPath);
124 | switch(type)
125 | {
126 | case 1:
127 | file.addEventListener(Event.SELECT,function(e:Event):void{
128 | onSelect(e.target as File);
129 | });
130 | file.browseForOpen(title,typeFilter);
131 | break;
132 | case 2:
133 | file.addEventListener(FileListEvent.SELECT_MULTIPLE,function(e:FileListEvent):void{
134 | onSelect(e.files);
135 | });
136 | file.browseForOpenMultiple(title,typeFilter);
137 | break;
138 | case 3:
139 | file.addEventListener(Event.SELECT,function(e:Event):void{
140 | onSelect(e.target as File);
141 | });
142 | file.browseForDirectory(title);
143 | break;
144 | }
145 | }
146 |
147 | /**
148 | * 打开保存文件对话框,选择要保存的路径。要同时保存数据请使用browsewAndSave()方法。
149 | * @param onSelect 回调函数:onSelect(file:File)
150 | * @param defaultPath 默认路径
151 | * @param title 对话框标题
152 | */
153 | public static function browseForSave(onSelect:Function,defaultPath:String=null,title:String="保存文件"):void
154 | {
155 | defaultPath = escapePath(defaultPath);
156 | var file:File
157 | if(defaultPath!=null)
158 | file = File.applicationDirectory.resolvePath(defaultPath);
159 | else
160 | file = new File;
161 | file.addEventListener(Event.SELECT,function(e:Event):void{
162 | onSelect(e.target as File);
163 | });
164 | file.browseForSave(title);
165 | }
166 |
167 | /**
168 | * 打开保存文件对话框,并保存数据。
169 | * @param data
170 | * @param onSelect 回调函数:onSelect(file:File)
171 | * @param title 对话框标题
172 | */
173 | public static function browseAndSave(data:Object,defaultPath:String=null,title:String="保存文件"):void
174 | {
175 | defaultPath = escapePath(defaultPath);
176 | var file:File
177 | if(defaultPath!=null)
178 | file = File.applicationDirectory.resolvePath(defaultPath);
179 | else
180 | file = new File;
181 | file.addEventListener(Event.SELECT,function(e:Event):void{
182 | save(file.nativePath,data);
183 | });
184 | file.browseForSave(title);
185 | }
186 |
187 | /**
188 | * 移动文件或目录,返回是否移动成功
189 | * @param source 文件源路径
190 | * @param dest 文件要移动到的目标路径
191 | * @param overwrite 是否覆盖同名文件
192 | */
193 | public static function moveTo(source:String,dest:String,overwrite:Boolean=false):Boolean
194 | {
195 | source = escapePath(source);
196 | dest = escapePath(dest);
197 | if(source==dest)
198 | return true;
199 | var file:File = new File(File.applicationDirectory.resolvePath(source).nativePath);
200 | //必须创建绝对位置的File才能移动成功。
201 | var destFile:File = new File(File.applicationDirectory.resolvePath(dest).nativePath);
202 | if(destFile.exists)
203 | deletePath(destFile.nativePath);
204 | try
205 | {
206 | file.moveTo(destFile,overwrite);
207 | }
208 | catch(e:Error)
209 | {
210 | return false;
211 | }
212 | return true;
213 | }
214 |
215 | /**
216 | * 复制文件或目录,返回是否复制成功
217 | * @param source 文件源路径
218 | * @param dest 文件要移动到的目标路径
219 | * @param overwrite 是否覆盖同名文件
220 | */
221 | public static function copyTo(source:String,dest:String,overwrite:Boolean=false):Boolean
222 | {
223 | source = escapePath(source);
224 | dest = escapePath(dest);
225 | if(source==dest)
226 | return true;
227 | var file:File = File.applicationDirectory.resolvePath(source);
228 | //必须创建绝对位置的File才能移动成功。
229 | var destFile:File = new File(File.applicationDirectory.resolvePath(dest).nativePath);
230 | if(destFile.exists)
231 | deletePath(destFile.nativePath);
232 | try
233 | {
234 | file.copyTo(destFile,overwrite);
235 | }
236 | catch(e:Error)
237 | {
238 | return false;
239 | }
240 | return true;
241 | }
242 |
243 | /**
244 | * 删除文件或目录,返回是否删除成功
245 | * @param path 要删除的文件源路径
246 | * @param moveToTrash 是否只是移动到回收站,默认false,直接删除。
247 | */
248 | public static function deletePath(path:String,moveToTrash:Boolean = false):Boolean
249 | {
250 | path = escapePath(path);
251 | var file:File = new File(File.applicationDirectory.resolvePath(path).nativePath);
252 | if(moveToTrash)
253 | {
254 | try
255 | {
256 | file.moveToTrash();
257 | }
258 | catch(e:Error)
259 | {
260 | return false;
261 | }
262 | }
263 | else
264 | {
265 | if(file.isDirectory)
266 | {
267 | try
268 | {
269 | file.deleteDirectory(true);
270 | }
271 | catch(e:Error)
272 | {
273 | return false;
274 | }
275 | }
276 | else
277 | {
278 | try
279 | {
280 | file.deleteFile();
281 | }
282 | catch(e:Error)
283 | {
284 | return false;
285 | }
286 | }
287 | }
288 | return true;
289 | }
290 |
291 | /**
292 | * 返回指定文件的父级文件夹路径,返回字符串的结尾已包含分隔符。
293 | */
294 | public static function getDirectory(path:String):String
295 | {
296 | path = escapeUrl(path);
297 | var endIndex:int = path.lastIndexOf("/");
298 | if(endIndex==-1)
299 | {
300 | return "";
301 | }
302 | return path.substr(0,endIndex+1);
303 | }
304 | /**
305 | * 获得路径的扩展名
306 | */
307 | public static function getExtension(path:String):String
308 | {
309 | path = escapeUrl(path);
310 | var index:int = path.lastIndexOf(".");
311 | if(index==-1)
312 | return "";
313 | var i:int = path.lastIndexOf("/");
314 | if(i>index)
315 | return "";
316 | return path.substring(index+1);
317 | }
318 | /**
319 | * 获取路径的文件名(不含扩展名)或文件夹名
320 | */
321 | public static function getFileName(path:String):String
322 | {
323 | if(path==null||path=="")
324 | return "";
325 | path = escapeUrl(path);
326 | var startIndex:int = path.lastIndexOf("/");
327 | var endIndex:int;
328 | if(startIndex>0&&startIndex==path.length-1)
329 | {
330 | path = path.substring(0,path.length-1);
331 | startIndex = path.lastIndexOf("/");
332 | endIndex = path.length;
333 | return path.substring(startIndex+1,endIndex);
334 | }
335 | endIndex = path.lastIndexOf(".");
336 | if(endIndex==-1)
337 | endIndex = path.length;
338 | return path.substring(startIndex+1,endIndex);
339 | }
340 |
341 | /**
342 | * 搜索指定文件夹及其子文件夹下所有的文件
343 | * @param dir 要搜索的文件夹
344 | * @param extension 要搜索的文件扩展名,例如:"png"。不设置表示获取所有类型文件。注意:若设置了filterFunc,则忽略此参数。
345 | * @param filterFunc 过滤函数:filterFunc(file:File):Boolean,参数为遍历过程中的每一个文件夹或文件,返回true则加入结果列表或继续向下查找。
346 | * @return File对象列表
347 | */
348 | public static function search(dir:String,extension:String=null,filterFunc:Function=null):Array
349 | {
350 | dir = escapePath(dir);
351 | var file:File = File.applicationDirectory.resolvePath(dir);
352 | var result:Array = [];
353 | if(!file.isDirectory)
354 | return result;
355 | extension = extension?extension.toLowerCase():"";
356 | findFiles(file,result,extension,filterFunc);
357 | return result;
358 | }
359 | /**
360 | * 递归搜索文件
361 | */
362 | private static function findFiles(dir:File,result:Array,
363 | extension:String=null,filterFunc:Function=null):void
364 | {
365 | var fileList:Array = dir.getDirectoryListing();
366 | for each(var file:File in fileList)
367 | {
368 | if(file.isDirectory)
369 | {
370 | if(filterFunc!=null)
371 | {
372 | if(filterFunc(file))
373 | {
374 | findFiles(file,result,extension,filterFunc);
375 | }
376 | }
377 | else
378 | {
379 | findFiles(file,result,extension,filterFunc);
380 | }
381 | }
382 | else if(filterFunc!=null)
383 | {
384 | if(filterFunc(file))
385 | {
386 | result.push(file);
387 | }
388 | }
389 | else if(extension)
390 | {
391 | if(file.extension&&file.extension.toLowerCase() == extension)
392 | {
393 | result.push(file);
394 | }
395 | }
396 | else
397 | {
398 | result.push(file);
399 | }
400 | }
401 | }
402 |
403 | /**
404 | * 将url转换为本地路径
405 | */
406 | public static function url2Path(url:String):String
407 | {
408 | url = escapePath(url);
409 | var file:File = File.applicationDirectory.resolvePath(url);
410 | return escapeUrl(file.nativePath);
411 | }
412 | /**
413 | * 将本地路径转换为url
414 | */
415 | public static function path2Url(path:String):String
416 | {
417 | path = escapePath(path);
418 | return File.applicationDirectory.resolvePath(path).url;
419 | }
420 | /**
421 | * 指定路径的文件或文件夹是否存在
422 | */
423 | public static function exists(path:String):Boolean
424 | {
425 | path = escapePath(path);
426 | var file:File = File.applicationDirectory.resolvePath(path);
427 | return file.exists;
428 | }
429 | /**
430 | * 转换本机路径或url为Unix风格路径。若是文件夹路径,返回值结尾已包含分隔符。
431 | */
432 | public static function escapePath(path:String):String
433 | {
434 | if(!path)
435 | return "";
436 | if(path.indexOf("file:")==0)
437 | {
438 | try
439 | {
440 | var file:File = new File();
441 | file.url = path;
442 | path = file.nativePath;
443 | }
444 | catch(e:Error)
445 | {
446 | }
447 | }
448 | try
449 | {
450 | file = new File(path);
451 | if(file.exists)
452 | {
453 | if(file.isDirectory)
454 | path = file.nativePath+File.separator;
455 | }
456 | else
457 | {
458 | var ext:String = getExtension(path);
459 | if(!ext)
460 | path = file.nativePath+File.separator;
461 | }
462 | }
463 | catch(e:Error)
464 | {
465 | }
466 | path = path.split("\\").join("/");
467 | return path;
468 | }
469 | /**
470 | * 转换url中的反斜杠为斜杠
471 | */
472 | public static function escapeUrl(url:String):String
473 | {
474 | return Boolean(!url)?"":url.split("\\").join("/");
475 | }
476 | }
477 | }
--------------------------------------------------------------------------------
/src/com/domlib/utils/StringUtil.as:
--------------------------------------------------------------------------------
1 | package com.domlib.utils
2 | {
3 | /**
4 | * 字符串工具类
5 | * @author dom
6 | */
7 | public class StringUtil
8 | {
9 | /**
10 | * 去掉字符串两端所有连续的不可见字符。
11 | * 注意:若目标字符串为null或不含有任何可见字符,将输出空字符串""。
12 | * @param str 要格式化的字符串
13 | */
14 | public static function trim(str:String):String
15 | {
16 | return trimLeft(trimRight(str));
17 | }
18 | /**
19 | * 去除字符串左边所有连续的不可见字符。
20 | * @param str 要格式化的字符串
21 | */
22 | public static function trimLeft(str:String):String
23 | {
24 | if(!str)
25 | return "";
26 | var char:String = str.charAt(0);
27 | while(str.length>0&&
28 | (char==" "||char=="\t"||char=="\n"||char=="\r"||char=="\f"))
29 | {
30 | str = str.substr(1);
31 | char = str.charAt(0);
32 | }
33 | return str;
34 | }
35 | /**
36 | * 去除字符串右边所有连续的不可见字符。
37 | * @param str 要格式化的字符串
38 | */
39 | public static function trimRight(str:String):String
40 | {
41 | if(!str)
42 | return "";
43 | var char:String = str.charAt(str.length-1);
44 | while(str.length>0&&
45 | (char==" "||char=="\t"||char=="\n"||char=="\r"||char=="\f"))
46 | {
47 | str = str.substr(0,str.length-1);
48 | char = str.charAt(str.length-1);
49 | }
50 | return str;
51 | }
52 |
53 | /**
54 | * 替换指定的字符串里所有的p为rep
55 | */
56 | public static function replaceStr(targetStr:String,p:String,rep:String):String
57 | {
58 | if(!targetStr)
59 | return "";
60 | var arr:Array = targetStr.split(p);
61 | return arr.join(rep);
62 | }
63 | /**
64 | * 将颜色数字代码转换为字符串。
65 | */
66 | public static function toColorString(color:uint):String
67 | {
68 | var str:String = color.toString(16).toUpperCase();
69 | var num:int = 6-str.length;
70 | for(var i:int=0;i1073741824)
87 | {
88 | sizeStr += int(length/1073741824).toString()+"GB";
89 | length = length%1073741824;
90 | }
91 | if(length>1048576)
92 | {
93 | if(sizeStr)
94 | sizeStr += ",";
95 | sizeStr += int(length/1048576).toString()+"MB";
96 | length = length%1048576;
97 | }
98 | if(length>1204)
99 | {
100 | if(sizeStr)
101 | sizeStr += ",";
102 | sizeStr += int(length/1204).toString()+"KB";
103 | length = length%1204;
104 | }
105 | if(length>0)
106 | {
107 | if(sizeStr)
108 | sizeStr += ",";
109 | sizeStr += length.toString()+"B";
110 | }
111 | }
112 | else
113 | {
114 | if(length>1073741824)
115 | {
116 | sizeStr = Number(length/1073741824).toFixed(fractionDigits)+"GB";
117 | }
118 | else if(length>1048576)
119 | {
120 | sizeStr = Number(length/1048576).toFixed(fractionDigits)+"MB";
121 | }
122 | else if(length>1204)
123 | {
124 | sizeStr = Number(length/1204).toFixed(fractionDigits)+"KB";
125 | }
126 | else
127 | {
128 | sizeStr = length.toString()+"B";
129 | }
130 | }
131 | return sizeStr;
132 | }
133 |
134 | private static var htmlEntities:Array = [["&","&"],["<","<"],[">",">"],["\"","""],["'","'"]];
135 | /**
136 | * 转换为HTML实体字符
137 | */
138 | public static function escapeHTMLEntity(str:String):String
139 | {
140 | if(!str)
141 | return "";
142 | var list:Array = htmlEntities;
143 | for each(var arr:Array in list)
144 | {
145 | var key:String = arr[0];
146 | var value:String = arr[1];
147 | str = str.split(key).join(value);
148 | }
149 | return str;
150 | }
151 | /**
152 | * 转换HTML实体字符为普通字符
153 | */
154 | public static function unescapeHTMLEntity(str:String):String
155 | {
156 | if(!str)
157 | return "";
158 | var list:Array = htmlEntities;
159 | for each(var arr:Array in list)
160 | {
161 | var key:String = arr[0];
162 | var value:String = arr[1];
163 | str = str.split(value).join(key);
164 | }
165 | return str;
166 | }
167 | }
168 | }
--------------------------------------------------------------------------------
/src/encrypt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | E:/Program/Flash/FlexLiteStudio2/src
4 | E:/Program/Flash/FlexLiteDesktop/src
5 |
6 |
7 | E:/Program/Flash/FlexLite/bin/FlexLite.swc
8 | E:/Program/Flash/FlexLiteStudio2/bin-debug/bin/libs/playerglobal.swc
9 |
10 |
11 | E:/Program/Flash/FlexLiteStudio2/doc/keyword.amf
12 |
13 |
14 | E:/Program/Flash/FlexLiteStudio2_MIX/src/
15 |
16 |
--------------------------------------------------------------------------------