├── .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 | --------------------------------------------------------------------------------