<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Vincent.Chan‘s Blog

    常用鏈接

    統(tǒng)計

    積分與排名

    網(wǎng)站

    最新評論

    LumaQQ源代碼指南

    對于有些喜歡修改源代碼的人,這里是一個指南的開端。我想到什么說什么,第一篇說說如何修改源代碼讓你用TM登錄。

    你不想使用QQ登錄,想使用TM登錄么?通過修改源代碼,是很簡單的。

    其實TM和QQ的協(xié)議是一樣的,雖然有些功能TM有QQ沒有,但是基本上都不是服務(wù)器的限制。舉個例子說,TM里面有個“隱身對某人可見”功能,命令是0x0024,雖然QQ里面沒有這個功能,但是你如果真的通過QQ發(fā)送這個命令,服務(wù)器目前是不會拒絕的。

    PS: 所以我一直覺得TM不過是界面改改罷了,里面的東西,照舊。

    我們看一下QQ.java, 有這么一個常量
    public static final char QQ_CLIENT = QQ_CLIENT_0E1B;
    你把他改成
    public static final char QQ_CLIENT = 0x0F0A;

    然后你再運行,LumaQQ就成了LumaTM了

    基本上啥也沒干,是不是。QQ_CLIENT是版本標(biāo)識,0x0F0A表示的是TM 2006新春版。TM和QQ基本上就這點差別。也許夸張了點。

    你怎么知道修改了這個常量就是TM了?假設(shè)你有兩個號碼A和B,你用騰訊TM把A設(shè)成隱身對B可見。然后嘗試用LumaQQ登錄A,看看修改前后在B的那邊有沒有區(qū)別,就知道了。

    但是LumaTM還是QQ界面?這...,這不指南才開始嗎?哪有空把界面怎么改都一次說全了。

    你解析了一個未知的包,不知道怎么添加到JQL么?如果你有這樣的疑問,我給你一些指南

    一般來說,你要完成以下任務(wù):
    1. 添加相應(yīng)的命令常量到QQ.java
    2. 根據(jù)協(xié)議族不同,繼承不同的基類。以基本協(xié)議族為例,繼承BasicOutPacket,創(chuàng)建一個輸出包類。再繼承BasicInPacket,創(chuàng)建一個輸入包類。你可以看看現(xiàn)有的包,抄一個過來,然后修改putBody或者parseBody就可以了。
    3. 根據(jù)協(xié)議族不同,找到不同的parser,以基本協(xié)議族為例,看看BasicParser.java,他負(fù)責(zé)解析所有基本協(xié)議族的包,把你的包加到parseIncoming和parseOutcoming的大switch里面吧
    4. 你的包是否觸發(fā)一些事件?如果是,修改QQEvent.java,添加你自己的事件常量。千萬不要和其他的事件常量沖突了,我在里面標(biāo)明了下一個可用的事件ID。
    5. 根據(jù)協(xié)議族不同,找到不同的包事件處理器。以基本協(xié)議族為例,看看BasicFamilyProcessor.java,那個packetArrived的大switch里面。加上你自己的代碼,觸發(fā)你的事件吧。
    6. 找到QQClient.java,添加一個方便的方法可以發(fā)送你的包,不加其實沒事,但是加了好些,上層調(diào)用起來方便。

    還好步驟不算很多,Just do it!

    想把圖標(biāo)都換換?這個簡單

    edu.tsinghua.lumaqq.resource.icon,程序的圖標(biāo)
    edu.tsinghua.lumaqq.resource.head,用戶頭像
    edu.tsinghua.lumaqq.resource.smallhead,用戶小頭像
    edu.tsinghua.lumaqq.resource.clusterhead,群頭像
    edu.tsinghua.lumaqq.resource.face,缺省表情
    edu.tsinghua.lumaqq.resource.image,一些比較大的圖片,logo,背景什么的

    看哪個不順眼,換吧。但是文件名和圖片尺寸不要亂變。

    你嫌LumaQQ的機器人實現(xiàn)太簡單么?是簡單了點,我只處理了普通消息,你想讓機器人也回復(fù)群消息,也回復(fù)手機短信,等等。

    不麻煩,稍微改改QQClient.java吧,找找qqEvent方法,有這么一塊
    case QQEvent.QQ_RECEIVE_NORMAL_IM:
    processNormalIM(e);
    break;

    processNormalIM很簡單:
    // 先返回確認(rèn)
    processReceiveIM(e);

    // 得到消息包
    ReceiveIMPacket packet = (ReceiveIMPacket)e.getSource();
    doRobot(packet);

    so,把下面加到qqEvent里面
    case QQEvent.QQ_RECEIVE_CLUSTER_IM:
    processClusterIM(e);
    break;

    再加一個processClusterIM方法:
    // 先返回確認(rèn)
    processReceiveIM(e);

    // 得到消息包
    ReceiveIMPacket packet = (ReceiveIMPacket)e.getSource();
    doRobot(packet);

    這樣就可以讓robot也收到群消息了,剩下的事,是你的Robot實現(xiàn)的事。doRobot方法里面只發(fā)送普通消息,所以要改一下,具體就不說了


    想改變整個程序的樣式么? 工作有點多

    我沒有實現(xiàn)什么皮膚,只是簡單的做了一些程序邊框的修飾,主要的工作都是在BorderStyler.java里面完成的。

    BorderStyler 的工作就是你傳一個shell進去,它給shell加上邊框,標(biāo)題條,還有最大最小之類的按鈕,當(dāng)然還要添加一些事件監(jiān)聽器。你要改也可以,不過我覺得基 本上BorderStyler沒有太多需要改的。你可以換換顏色,換換那些按鈕的圖標(biāo),這樣界面風(fēng)格就可以變了。

    大部分顏色都定義在Colors.java里面,你可以改。
    最大化最小化按鈕的圖片在指南(2)里面有介紹,還有一些背景圖,也可以改了以便和按鈕的色調(diào)配合
    光改了邊框恐怕還不行,其他控件的顏色方案也得改改吧,比如好友列表的顏色方案。

    如果有些控件用到的顏色沒有在Colors里面定義,那你得稍微改改控件的代碼。

    記得我在指南(2)里面說過的,改圖片的時候不要亂改圖片大小。

    01-17版本改寫了聊天記錄導(dǎo)出的架構(gòu),稍微靈活了一些,不過實現(xiàn)的也不是太好,意思一下就是了啦

    我缺省做了兩個簡單的聊天記錄導(dǎo)出模板,文本的和HTML的,如果你想添加自己的模板,或者修改現(xiàn)有的模板,可以看看LumaQQ_template工程,這是一個剛創(chuàng)建的新工程,為了正確的使用這個工程,你需要裝EMF,我用了JET來做模板

    template下面就是jet的模板定義,這個工程文件不多,除了RecordExporterFactory是手寫的,其他的代碼都是從jet模板生成的。

    RecordExporterFactory很簡單,隨便看看也就明白了,如果你想加個自己的模板上去,照著樣子加點代碼,然后寫一下自己的模板文件,然后執(zhí)行build.xml的jar目標(biāo),然后把jar拷貝到LumaQQ_2005的lib里面,然后沒有了

    實現(xiàn)的不是太強,夠用就行。對JET感興趣的,安裝完EMF之后,eclipse的幫助里面會有兩篇JET的文章。Eclipse主頁也有。

    Windows下面沒有熱鍵,等著你們來實現(xiàn)

    其實Windows下面實現(xiàn)熱鍵很簡單,比linux簡單。有人愿意寫就寫吧,這個我接受你的contribution,并且會加你到About對話框的,當(dāng)然你實現(xiàn)的要有質(zhì)量。

    自然了,這一塊不得不用JNI,接口是很簡單的,就三個方法,具體去看看edu.tsinghua.lumaqq.hotkey.linux.edu_tsinghua_lumaqq_hotkey_KeyBinder.h文件,三個方法的原型在那里。

    簡單說一下這三個方法:
    init: 初始化
    bind: 綁定一個熱鍵,熱鍵用字符串的形式描述,比如Z,綁定成功返回true,否則返回false
    unbind: 取消綁定,參數(shù)和bind一樣,沒有返回值。

    接口很簡單,能用就行。怎么實現(xiàn)熱鍵我是指導(dǎo)不了你了,反正Windows就是鉤子嘛

    LumaQQ有個Debugger,還是很好玩的吧?你有沒有想自己寫一個debugger UI,或者讓LumaQQ的debugger功能更強?

    Debug的支持是嵌入在JQL協(xié)議層的,而界面怎么實現(xiàn)是留給你去完成的。所以這部分代碼分成兩個部分:
    1. jql_protocol: edu.tsinghua.lumaqq.qq.debug包: Debug的核心支持
    2. LumaQQ: edu.tsinghua.lumaqq.ui.debug包: LumaQQ自帶的debugger UI實現(xiàn)

    看起來很牛B其實debug功能很有限,也就是讓你看看收發(fā)了些什么包而已吧。如果你還想要監(jiān)控核心層其他的活動,那這個就要你去擴展了,不過我覺得能看看包也就行了,其他的功能,因為我自己沒這個需求,自然就沒做。

    Debug 在核心層的支持是可以通過DebugSwitch.java來切換的,唯一增加的開銷是一個if檢查,所以這點我還是比較滿意的。核心層在開通了 Debug功能后,會把所有的收到和發(fā)送的包都傳給你,當(dāng)然你必須要添加個IDebugListener才能收到這些包。現(xiàn)在找到 edu.tsinghua.lumaqq.qq包,查看Packet.java和OutPacket.java,你可以發(fā)現(xiàn)一些Debug功能的相關(guān)代 碼,這是為什么所有的包都可以被監(jiān)視的原因。

    至于UI的實現(xiàn),那可以很靈活,具體的就看主頁文檔,看看缺省的調(diào)試器是怎么做的。

    對于寫界面來說,很大的功夫都花在了寫組件上。為了界面盡量好看點,我寫了一些自繪的組件。之所以沒去實現(xiàn)皮膚,那是因為太繁瑣了,沒必要。

    在edu.tsinghua.lumaqq.widgets下面,都是LumaQQ用到的一些組件。這些組件你可以直接拿去用。

    edu.tsinghua.lumaqq.widgets: 一些尚未歸類的組件,主要是表情頭像選擇的那個窗口: ImageSelector.java。通過實現(xiàn)IImageSelectorAdvisor接口,可以指定窗口的一些樣式和可選擇的圖片內(nèi)容。

    edu.tsinghua.lumaqq.widgets.mac: 這下面目前只有一個組件,Ring.java。從包名來看,這下面的組件是一些Mac風(fēng)格的組件,如果你用過Mac,也許你對Mac的那個轉(zhuǎn)來轉(zhuǎn)去的 Busy指示器有點印象,Ring就是這個玩意。Ring.java負(fù)責(zé)處理通用的邏輯,轉(zhuǎn)圈的方式是可以擴展的。缺省的實現(xiàn)是圓形的,如果你想要個其他 形狀的,比如說,正方形;那么擴展IBorderPainter和ISignPainter就可以了。具體可以參考缺省的圓形實現(xiàn)。

    edu.tsinghua.lumaqq.widgets.menu: 這里面是一個自定義的菜單實現(xiàn),沒辦法的產(chǎn)物。在Linux下面窗口置頂時,菜單出不來,只好自己寫了一個簡單菜單的實現(xiàn)。優(yōu)點是想怎么畫就怎么畫,美觀 有所提高。缺點是帶來了一個bug,不點一下窗口其他地方菜單不會消息,很難處理,現(xiàn)在也沒解決,不過想來想去,這個bug不是太嚴(yán)重,所以也就忍了。

    edu.tsinghua.lumaqq.widgets.qstyle: 看名字可知,這是QQ樣式的組件。QQ什么樣式?比如QQ那個好友列表,QQ的button,等等。最主要的是QQ的好友列表,為了獲得和QQ一樣的視覺 效果,這個好友列表是最重要的部分。首先windows不提供這樣的控件,SWT也沒有,只好自己寫。在2004之前,用的叫Shutter,由于速度上 不行,后來改寫了,叫做Blind,這兩個單詞都是百葉窗的意思。Shutter已經(jīng)拋棄了,就不提了。稍微說一下Blind。Blind實際上是一個組 合組件,并不是自繪的。Blind上面的按鈕是Slat,實際的內(nèi)容區(qū)域是Composite子類。在LumaQQ里面,Blind里面的內(nèi)容是 QTree組件,QTree是自繪的,它有QItem組成,QTreeViewer呢,是QTree的MVC封裝。主要的重繪工作在QItem里面,一個 Item(形象一點說,一個好友)分成了很多部分,好友的頭像是主圖標(biāo),好友的昵稱是文本,好友離開的時候,頭像的右下有個小圖標(biāo),這叫裝飾,好友如果是 綁定手機用戶,頭像旁邊會有手機圖標(biāo),這叫附件,在群里面,還可以看到群下面有組織,可以收起展開,圖標(biāo)的前面會有加號減號標(biāo)明是否展開,這叫前綴。是不 是有點暈了。QItem從QTree哪里得到一個重繪的起始位置,它自己負(fù)責(zé)計算出裝飾,附件,前綴,文本的位置,然后重畫。為了支持動畫,提供了 IEffect接口讓用戶可以自定義重畫的行為,可以參考IEffect的實現(xiàn)類查看具體的實現(xiàn)。Slat呢,就是QQ樣式的button,也是自繪的, 比較簡單。LevelBar是一個等級條,用來顯示好友的等級,缺省使用太遠月亮星星來表示,圖標(biāo)是可以換的,提供了API設(shè)置。Bubble是一個 MSN那樣的冒泡窗口的簡單實現(xiàn),還沒有在LumaQQ里面用到,DieAway呢,是一個淡入淡出的窗口,QQ上線提示那樣的,不過也沒有用到。
    By luma at 01/25/2006 - 16:51 | 發(fā)表評論 | 更多 | 435 reads
    2005的結(jié)束

    這 幾天想想還有什么可以做的,想不太出來,除了文件傳輸這一塊。Bug報告的數(shù)量緩慢,難道bug越來越少?Eclipse 3.2猶抱琵琶,何時才能讓我體驗新特性,提交了幾個Eclipse bug現(xiàn)在也不解,真難等哪。所以,還是結(jié)束吧,繼續(xù)開始下一個Buggy的版本吧。

    雖然讓我無語的人不少,還是要感謝大家對我的支持。每個星期10多萬的點擊數(shù)也不少,可惜不是點廣告的次數(shù),哈,肯定是比不上如來神掌威風(fēng)的時期了,回想起來還真是好玩捏。

    很 幸運,一些經(jīng)典bug得到了解決,使2005的穩(wěn)定性超越了2004T,對這點我很滿意。2006的任務(wù)是代碼重整和文件傳輸,自定義頭像和表情,還有 MSN集成。說任務(wù)是言重了,這只是我的平臺,是體驗Eclipse新特性的工具,是我的玩具,也是各位的玩具,抱著輕松的心情研究使用它吧。

    如來神掌,終究是浮云,QQ,遲早是浮云。一切就不要當(dāng)真了,沒有什么是我承諾給你的,也沒有什么是你肯定會獲得的,除了那些源代碼。

    LumaQQ里面用到了一些Wizard,比如在搜索的時候,在創(chuàng)建群的時候。JFace是帶了一個Wizard框架的,用的就是它的,只不過稍微改了一下。

    查看edu.tsinghua.lumaqq.ui.wizard,看到IModelBasedWizard.java,這里對IWizard做了兩個擴展,第一個是采用一個model對象來保存wizard中的信息,所以,你看到了,MVC模式是無處不在的。

    第 二個擴展是加了個preNext,用來在點Next按鈕之前做一些事情,這個需求源自對QQ的搜索功能的調(diào)查。QQ搜索的時候,有時候下一步并不是到下一 個page,而是打開一個瀏覽器去網(wǎng)頁上找了。JFace的wizard框架似乎是不能這樣做,所以我加了一個preNext方法。為了讓這個方法能夠被 觸發(fā),使用了WizardWindow類繼承WizardDialog以便能插入preNext方法,WizardWindow還有一個目的:使 Wizard窗口成為獨立窗口,而不是對話框(如果是對話框的話,主窗口最小化,它也會不見,所以要改成獨立窗口的),這個主要是重載 getParentShell方法,讓它返回null,雖然這個方法不是很推薦,但是似乎簡單又方便。

    其他的內(nèi)容就沒有什么奇怪了,按照J(rèn)Face的標(biāo)準(zhǔn)框架走下來就可以了。可能有人覺得wizard那些按鈕都是英文的不爽,這個可以通過修改jface的jar包里面的properties文件來改,你可以試試。

    QQ的協(xié)議非常龐大,怎么統(tǒng)一的描述包的結(jié)構(gòu),是一個很麻煩的問題。騰訊的包是不是有個統(tǒng)一的準(zhǔn)則,不清楚,當(dāng)然從設(shè)計上來說,統(tǒng)一的當(dāng)然好。

    以前以為QQ的包就那么多,設(shè)計的簡單化了。后來功能越加越多,就接觸了一些沒見過的包,發(fā)現(xiàn)類結(jié)構(gòu)描述不了,所以只好改寫,目前的結(jié)構(gòu)是一個4層的模型,真的夠用嗎?目前來說還湊合

    首先我們得了解一下QQ那么多包的共同點和不同點,才好了解JQL中的類結(jié)構(gòu)。
    1. 目前看來,QQ的包有包頭,包體,包尾之分,但是包尾在某些協(xié)議族里面是個可選的玩意兒
    2. 在某些協(xié)議族里面,包格式又有TCP和UDP之分,有些沒有。抽象一點來說呢,UDP是簡單的,隨便定義什么格式都可以滿足要求,TCP是連續(xù)的數(shù)據(jù)流,在連續(xù)的數(shù)據(jù)流里面解析包,就需要有包長度的描述。
    3. 包體有全加密,不加密和部分加密的區(qū)別
    4. 包有輸入和輸出包之分,不過在有些協(xié)議族里面這個區(qū)別不明顯,甚至可以說輸入和輸出包是一樣的格式

    為了能夠描述現(xiàn)有的包,并且能夠為未知的新包提供兼容,目前類的層次有這樣4層,相關(guān)源代碼請查看edu.tsinghua.lumaqq.qq.packets包和子包
    1. 一個頂層的基類Packet。它提供最基本的描述和很多抽象的方法。比如一些通用的字段,還有一些通用的方法,但是這個基類的大部分內(nèi)容還是抽象方法,留 待子類實現(xiàn)。Packet最重要的地方在于提供了一個基本的模型,就是把包的構(gòu)造和解析過程分成了頭,體,尾三部分。你可以找到putHead, putBody, putTail方法用于構(gòu)造一個包,可以找到parseHead, parseBody, parseTail方法用于解析一個包。
    2. 兩個Packet的子類InPacket和OutPacket提供對輸入和輸出包的最基本封裝。Packet類是通用的模型,其不涉及輸入和輸出包有什么 不同,所以我們需要這兩個子類來提供更具體的描述。InPacket很簡單,沒什么太多內(nèi)容,因為解析包的過程是通用的,封裝在了Packet中,所以 InPacket沒有多少事做。主要是OutPacket多了不少專用于輸出包的方法,比如重發(fā)次數(shù),超時時間等等,還封裝了輸出包的填充過程。查看 OutPacket的fill方法,可以看到輸出包的生成過程。

    在對網(wǎng)絡(luò)硬盤協(xié)議的分析中,發(fā)現(xiàn)有必要對JQL進行重構(gòu),以實現(xiàn)更靈活的協(xié)議建模和調(diào)試

    主要改變在
    1. 增加了PortPolicy類,隔離網(wǎng)絡(luò)收發(fā)和包解析功能,簡化了Port和協(xié)議之間的綁定操作
    2. 簡化了IParser接口,刪除了很多不必要的方法,更加簡潔
    3. 細分調(diào)試包對象,使其對應(yīng)于特定協(xié)議族
    4. 由于PortPolicy的引入,導(dǎo)致了其他一些類的相應(yīng)修改,比較瑣碎,不提了
    5. 細分超時事件,使其對應(yīng)于特定協(xié)議族
    6. 在Packet中增加getFamily方法,明確標(biāo)識包所屬協(xié)議族,拋棄以往使用header標(biāo)識包協(xié)議族的方式
    7. 不再允許Port直接觸發(fā)QQ事件,降低了他們之間的耦合

    重構(gòu)無止境,但是目前這樣已經(jīng)能滿足我增加網(wǎng)絡(luò)硬盤功能的需要,所以暫時就這樣。

    我們來了解一下自2006 M2之后,核心層有了什么樣的變化

    JQL里面有很多關(guān)鍵部件,先介紹一些概念
    1. Porter,啟動一個異步I/O循環(huán),直接監(jiān)聽網(wǎng)絡(luò)事件
    2. Port, 代表了一個端口,或者說代表了一個連接,Port需要注冊到Porter中,才能獲得網(wǎng)絡(luò)事件
    3. Parser,代表了一個解析器,用來解析某個協(xié)議族的包
    4. PacketHistory, 是包的緩沖,用來檢測重復(fù)包
    5. Processor,代表了一個處理器,用來處理某個協(xié)議族的包,繼而觸發(fā)QQ事件
    6. QQClient,代表了一個QQ客戶端

    在2006 M2之前
    1. 一個QQClient只有一個Porter
    2. 一個Porter可以有多個Port
    3. 在一個QQClient中,一個協(xié)議族只有一個Parser
    4. 在一個QQClient中,一個協(xié)議族一個Processor
    5. 一個QQClient只有一個PacketHistory

    那么在2006 M2之后
    1. 不變
    2. 不變
    3. 在一個Port中,一個協(xié)議族一個Parser,一個Port支持哪些協(xié)議族,通過PortPolicy指定
    4. 不變
    5. 一個Parser一個PacketHistory

    所以關(guān)鍵的改變在3,5。通過3,使Port更加靈活。通過5,使包重復(fù)檢測的機制更加靈活。其實,4也應(yīng)該變一下,但是目前沒需求,所以暫時不變。

    曾經(jīng)提過,這些改變是為了實現(xiàn)網(wǎng)絡(luò)硬盤功能的關(guān)系。網(wǎng)絡(luò)硬盤的協(xié)議和其他協(xié)議族有一些不同
    1. 網(wǎng)絡(luò)硬盤協(xié)議包并不完美匹配之前的包層次假設(shè)
    2. 網(wǎng)絡(luò)硬盤協(xié)議包可以非常長,帶來了解析上和處理上的新需求

    再細的我就不說了,自己領(lǐng)會

    posted on 2006-02-25 01:15 Vincent.Chen 閱讀(1116) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 精品久久久久久亚洲| 免费激情网站国产高清第一页| 亚洲欧洲久久久精品| 好吊妞在线新免费视频| 永久免费av无码网站yy| 午夜成人无码福利免费视频| 亚洲天堂2017无码中文| 久久亚洲AV无码精品色午夜麻豆| 国产精品亚洲玖玖玖在线观看| 日韩午夜免费视频| 在线观看无码AV网站永久免费| 99久久精品免费精品国产| CAOPORN国产精品免费视频| 免费一级全黄少妇性色生活片| 亚洲中文字幕一区精品自拍| 亚洲大片免费观看| 亚洲综合综合在线| 91亚洲一区二区在线观看不卡| 亚洲精品夜夜夜妓女网| 亚洲人成电影网站国产精品 | 在线免费观看亚洲| 日本亚洲成高清一区二区三区| 久久精品国产亚洲一区二区三区| 免费人成在线观看网站品爱网日本 | 久久精品免费全国观看国产| 久久A级毛片免费观看| 国产精品免费AV片在线观看| 国产成人免费ā片在线观看老同学 | 久久国产免费观看精品| 成人网站免费看黄A站视频| 日韩精品无码免费专区午夜| 成人精品一区二区三区不卡免费看 | 在线观看成人免费| 韩国日本好看电影免费看| 成人免费午夜视频| 在线看片人成视频免费无遮挡| 在线免费观看一级毛片| 国产不卡免费视频| 亚洲一区二区精品视频| 自拍偷自拍亚洲精品第1页| 国精无码欧精品亚洲一区|