本文系列共有三篇,前两篇链接在此:
《
EBT 道客巴巴的加密与破解 -免费下载器的基础》
写到这里有点忧伤,有两点,一是CSDN在删除我之前上传的附件,二是doc88.com服务器端没有完成破解,也就是说我只解开了doc88客户端。不想说什么,纯贴个代码就走。
AIR 项目主文件:
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="doWindowComplete(event);"
showStatusBar="false" minWidth="600" minHeight="400" maxWidth="600" maxHeight="420"
title="DOC88DD Downloader" >
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import dda.Coder;
import dda.JSAgent;
import dda.SmartClip;
import flash.desktop.Clipboard;
import flash.desktop.ClipboardFormats;
import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.ui.Keyboard;
import flash.utils.ByteArray;
import mx.controls.*;
import flash.filesystem.*;
import mx.events.*;
import spark.components.Group;
[Bindable]
private var _lod:URLLoader = new URLLoader();
private var _req:URLRequest = new URLRequest();
private var _jsa:JSAgent;
private var _clip:SmartClip;
private var _headers:Array;
private var _requestHeaders:Array = [
new URLRequestHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"),
new URLRequestHeader("Accept-Encoding","gzip, deflate, sdch"),
new URLRequestHeader("Accept-Language", "zh-CN,zh;q=0.8"),
new URLRequestHeader("Cache-Control", "no-cache"),
new URLRequestHeader("Referer", "www.baidu.com"),
//new URLRequestHeader("Host", "hiphotos.baidu.com"),
//new URLRequestHeader("x-flash-version: 16,0,0,252"),
//new URLRequestHeader("If-Modified-Since", "Mon, 01 Sep 2014 13:31:32 GMT"),
//new URLRequestHeader("If-None-Match", "7146584707648519807"),
new URLRequestHeader("Proxy-Connection", "keep-alive"),
//new URLRequestHeader("Cookie",""),
new URLRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36")
];
private var _symbols:String = "※◎★☆○●■△▲◇◆□■";
private var _tipOverlay:String = "An old file exists! Willing to update it or not?";
private var _tipDownloaded:String = "●File downloaded. (MB) binary store in memory inside PC.";
private var _tipDownload:String = "☆Downloading start:\n"
private var _tipTaskKill:String = "※ Downloading cancel";
private var _tipDisturbed:String = "A task is working. Press ESC to cancel."
private var _tipServerStatus:String = "Server return status: ";
private var _tipDoc88:String = "doc88.com detected and the js data distiled\n";
private var _tipSavePath:String = "★Save to Path:";
private var _tipDownloadClip:String = "Download smartclip URL:";
private var _tipSaveDirectory:String = "※Error: Save file to be a directory."
private var _tipNotDoc88:String = "※This file is not a doc88 data.";
private var _tipEbtInQueue:String = "Doc88.com ebt files in queue.";
private var _tipQueueFinish:String ="All files in queue has done."
private var _WEBHOST:RegExp = /^(https?:\/\/)?([\w-]+\.)+(\w{2,4})\/?/;
private var _DOC88REP:RegExp = /^http:\/\/www\.doc88\.com\/p-(\d+)\.html$/;
private var _WEBREP:RegExp = /^(https?:\/\/)?.+\..+\..{2,3}\//;
//private var _PLAINREP:RegExp = /\/|(\.html)$|(\.htm)$|(.txt)$|(js$)/;
private var _FileNameRep:RegExp = /([^\/\\\?#]+)(\?#?.*)?$/;
private var _ParserMap:Array = ["</head>", 0, "initWidth();", 1, "</script>", 0];
private var _File:File = new File();
private var _FileMask:Array = [
new FileFilter("script content", "*.js;*.as,*.cpp"),
new FileFilter("text content", "*.txt;*.log;*.inf")];
private function doWindowComplete(e:FlexEvent):void
{
btnOpen.addEventListener(MouseEvent.CLICK, doOpen);
txtFilePath.addEventListener(KeyboardEvent.KEY_UP, doKeyPress);
addEventListener(KeyboardEvent.KEY_UP, doAppKeyPress);
_clip = new SmartClip(function (smart:SmartClip, finish:Boolean):Boolean
{
if (_lod.hasEventListener(Event.COMPLETE)) return false;
if ( finish ) log(_tipQueueFinish);
log(_tipDownloadClip + smart.url);
openWebURL(smart.url);
return true;
});
}
private function openBrowser():void
{
_File.browseForOpen("Open", _FileMask);
_File.addEventListener(Event.SELECT, doSelect);
}
private function openWebURL(url:String):void
{
url = !/^http/.test(url)? "http://" + url:url;
_headers = null;
_req.url = url;
_req.method = URLRequestMethod.GET;
_req.useCache = false;
_req.cacheResponse = false;
_req.requestHeaders = _requestHeaders;
_req.manageCookies = false;
_lod.addEventListener(Event.COMPLETE, doComplete);
_lod.addEventListener(ErrorEvent.ERROR, doError);
_lod.addEventListener(IOErrorEvent.IO_ERROR, doError);
//_lod.addEventListener(HTTPStatusEvent.HTTP_STATUS, doResponse);
_lod.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, doResponse); // AIR only
_lod.addEventListener(ProgressEvent.PROGRESS, doProgress);
_lod.load(_req);
log( _tipDownload + url);
}
private function doAppKeyPress(e:KeyboardEvent):void
{
var sentinal:Boolean = _lod.hasEventListener(Event.COMPLETE);
switch(e.keyCode) {
case Keyboard.ESCAPE:
if (sentinal) {
_lod.close();
cleanListener();
log(_tipTaskKill+" "+url);
}
break;
default:
}
trace("KeyPress & keyCode = " + e.keyCode);
}
private function doKeyPress(e:KeyboardEvent):void
{
var sentinal:Boolean = _lod.hasEventListener(Event.COMPLETE);
// TextInput(e.target)==txtFilePath?
switch (e.keyCode)
{
case Keyboard.ENTER:
if( !sentinal ){
doOpen(new MouseEvent(MouseEvent.CLICK));
}else Alert.show(_tipDisturbed);
break;
default:
}
}
private function doProgress(e:ProgressEvent):void
{
// mode may set to MANUAL to coding progressbar. EVENT for default
if (e.bytesTotal == 0) {
_pgs.indeterminate = true;// no Content-Length
//_pgs.label = "Loading(B)".replace(e.bytesLoaded);
}else{
_pgs.setProgress(e.bytesLoaded, e.bytesTotal);
//trace("A/B".replace("A", e.bytesLoaded).replace("B", e.bytesTotal));
}
}
private function doComplete(e:Event):void
{
var df:String = _lod.dataFormat;
if ( df == URLLoaderDataFormat.TEXT && _DOC88REP.test(_req.url) && _lod.bytesTotal < 1024 * 1024 ) {
var js:String = _lod.data;
for (var k:Number = 0; k < _ParserMap.length; k+=2 ) {
var a:Array = js.split(_ParserMap[k])
var i:Number = _ParserMap[k+1];
js = a[i];
trace("\n\n" + _ParserMap[k] + " ORDER : " + i);
//trace("\n\nCompensated:"+a[1 - i]);
//trace(js);
}
txtContent.text = "";
txtContent.appendText(_tipDoc88);
txtContent.appendText(js?js:"null;");
if (js) {
var id:String = _DOC88REP.exec(_req.url)[1];
preSaveToFile("asts/data.id.js".replace("id",id), toByteArray(js));
initDoc88(js);
}
}else {
var bs:ByteArray = null;
if ( df != URLLoaderDataFormat.BINARY ) {
bs = new ByteArray()
bs.writeUTFBytes(_lod.data);
}else {
bs = _lod.data;
}
var KB:Number = 1024;
var MB:Number = 1024 * 1024;
var BS:Number = _lod.bytesTotal||_lod.bytesLoaded;
var mbs:Number = BS > MB? BS / MB:BS / KB;
log(_tipDownloaded.replace("MB", mbs.toFixed(2) + (BS > MB? "MB":"KB") ));
//var ps:String = _FileNameRep.exec(_req.url)[1];
//var d8:Array = _DOC88REP.exec(_req.url);
var ps:String = _req.url.replace(_WEBHOST, /\.ebt/.test(_req.url)? "ebt/":"./");
preSaveToFile(ps, bs);
}
cleanListener();
}
private function doResponse(e:HTTPStatusEvent):void
{
if(!_headers){
_headers = e.responseHeaders;
for (var i:int = 0; i < _headers.length; i++) {
var h:Object = _headers[i];
if (h.name == "Content-Type" && String(h.value).indexOf("text/html")<0) {
_lod.dataFormat = URLLoaderDataFormat.BINARY;
break;
}
}
}
if (e.status != 200) {
log(_tipServerStatus + e.status);
_lod.close();
cleanListener();
}else log(e.type + "=" + e.status);
}
private function doError(e:ErrorEvent):void
{
log(e.toString());
cleanListener();
}
private function cleanListener():void
{
_lod.removeEventListener(Event.COMPLETE, doComplete);
_lod.removeEventListener(ErrorEvent.ERROR, doError);
_lod.removeEventListener(ProgressEvent.PROGRESS, doProgress);
_lod.removeEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, doResponse);
_pgs.setProgress(100, 100);
_pgs.indeterminate = false;
}
private function doOpen(e:MouseEvent):void
{
var p:String = txtFilePath.text;
if (_WEBREP.test(p))
{
openWebURL(p);
return ;
}
if (txtFilePath.text) {
try{
_File = new File(txtFilePath.text);
trace("_File.exists="+_File.exists);
trace("_File.isDirectory=" + _File.isDirectory);
if ( _File.exists && !_File.isDirectory ) {
doOpenFile(_File);
return
}
}catch (er:Error) {
log(er.getStackTrace());
}
}
openBrowser();
}
private function doSelect(e:Event):void
{
_File = File(e.target);
doOpenFile(_File);
_File.removeEventListener(Event.SELECT, doSelect);
}
private function doOpenFile(file:File):void
{
var s:FileStream = new FileStream();
s.open(file, FileMode.READ);
txtFilePath.text = _File.nativePath;
txtContent.text = s.readUTFBytes(s.bytesAvailable);
s.close();
s = null;
initDoc88(txtContent.text);
btnModify.addEventListener(MouseEvent.CLICK, doModify);
}
private function initDoc88(data:String):void
{
var js:String = "<script>T</script>".replace("T", data);
_jsa = new JSAgent(js, function (o:Object):void
{
var nick_name:String = o.nick_name;
if (nick_name) {
doDoc88Decode();
}else {
log(_tipNotDoc88);
}
});
}
private function doDoc88Decode():void
{
var MPIB:String = _jsa.win.mpib;
var MPEBT:String = _jsa.win.mpebt;
var MAX_PAGE:Number = _jsa.win.mtp;
var MHI:Array = _jsa.win.mhi;
var MHOST:String = _jsa.win.mhost;
var KEYS:Array = Coder.decode(MPIB).split(",");
var fs:Array = new Array();
for ( var i:Number = 0; i < MAX_PAGE; i++) {
var ks:Array = KEYS[i].split("-");
var pk_size:Number = ks[4];
var NO_IDEA:Number = ks[3];
var height:Number = ks[2];
var width:Number = ks[1];
var hn:Number = ks[0];
var ph_size:Number = MHI[hn - 1];
var phk:String = hn + "-0-" + ph_size + "-" + MPEBT;
var pkk:String = hn + "-" + NO_IDEA + "-" + pk_size + "-" + MPEBT;
var ph_URL:String = MHOST + "/getebt-" + Coder.encode(phk) + ".ebt";
var pk_URL:String = MHOST + "/getebt-" + Coder.encode(pkk) + ".ebt";
fs.push(ph_URL, pk_URL);
}