<script type="text/javascript"> google_ad_client = "pub-5033576919944123"; google_ad_width = 728; google_ad_height = 90; google_ad_format = "728x90_as"; google_ad_type = "text_image"; //2007-10-24: csdn.blog google_ad_channel = "8548491739"; </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
MathMSN
MSN协议解析
首先连接到分派服务器messenger.hotmail.com的1863端口,执行下面三次握手。
C到S VER 1 MSNP13 CVR0/r/n/End
其中MSNP13表示使用第十三版本的协议,若服务器支持该版本的协议则返回
S到C VER 1 MSNP13 CVR0/r/n/End
C到S CVR 2 0x0804 winnt 5.0 i386 MSNMSGR 6.2.0133 MSMSGS xxx@hotmail.com
/r/n/End
此次握手只是一种形式,可以固定这样发送。其中xxx@hotmail.com是你要登陆的MSN帐号。
S到C CVR 2 7.0.0816 7.0.0816 6.2.0208
http://msgr.dlservice.microsoft.com/download/ 7/9/9 /79940907-8fbc-4eb1-a9bb-eee 592a 966b4/Install_MSN_Messenger_DL.EXE http://messenger.msn.com/cn/r/n/End
C到S USR 3 TWN I xxx@hotmail.com/r/n/End
其中xxx@hotmail.com是你要登陆的MSN帐号。
S到C XFR 3 NS 207.46.111.18:1863 U D/r/n/End
其中207.46.111.18:1863是你要连接的通知服务器的IP和端口。
断开与分派服务器的连接,连接到通知服务器207.46.111.18的1863端口,执行下面步骤。
C到S VER 4 MSNP13 CVR0/r/n/End
S到C VER 4 MSNP13 CVR0/r/n/End
C到S CVR 5 0x0804 winnt 5.0 i386 MSNMSGR 6.2.0133 MSMSGS xxx@hotmail.com
/r/n/End
S到C CVR 5 7.0.0816 7.0.0816 6.2.0208
http://msgr.dlservice.microsoft.com/download/ 7/9/9 /79940907-8fbc-4eb1-a9bb-eee 592a 966b4/Install_MSN_Messenger_DL.EXE http://messenger.msn.com/cn/r/n/End
C到S USR 6 TWN I xxx@hotmail.com/r/n/End
S到C GCF 0 5698/r/n【5698byte的数据】2USR 6 TWN S
lc=1033,id=507,tw=40,ru=http% 3A % 2F %2Fmessenger%2Emsn%2Ecom,ct=1175605256,kpp=1,kv=9,ver=2.1.6000.1,rn=qOzSvE*i,
tpf= 4a 85c 137e4ed067172138425903e6af3
/r/n/End
保存
“lc=1033,id=507,tw=40,ru=http% 3A % 2F %2Fmessenger%2Emsn%2Ecom,ct=1175605256,kpp=1,kv=9,ver=2.1.6000.1,rn=qOzSvE*i,
tpf= 4a 85c 137e4ed0671721384
25903e6af 3 ” 字符串和当前的网络连接。建立另一个SSL连接到nexus.passport.com服务器的443端口,执行下面步骤。
C到S GET /rdr/pprdr.asp HTTP/1.0/r/n/r/n/End
S到C HTTP/1.1 200 OK/r/n
Connection: close/r/n
Date: Tue, 03 Apr 2007 13:01:03 GMT/r/n
Server: Microsoft-IIS/6.0/r/n
PPServer: PPV: 30 H: BAYPPPRTS2B01 V: 0/r/n
X-Powered-By: ASP.NET/r/n
PassportURLs: DARealm=Passport.Net,DALogin=login.live.com/login2.srf,DAReg=
https://accountservices.passport.net/UIXPWiz.srf,Properties=
https://accountservices.msn.com/editprof.srf,Privacy=
https://accountservices.passport.net/PPPrivacyStatement.srf,
GeneralRedir=http://nexusrdr.passport.com/redir.asp,Help=
https://accountservices.passport.net,ConfigVersion=14/r/n
Content-Length: 0/r/n
Content-Type: text/html/r/n
Cache-control: private/r/n/r/n/End
截取上面加下划线部分的数据,断开当前SSL连接,重新建立另一个SSL连接到login.live.com服务器的443端口,执行下面步骤。
C到S GET /login2.srf HTTP/1.1/r/n
Host: login.live.com/r/n
Authorization: Passport1.4
OrgVerb=GET,OrgURL=http% 3A % 2F %2Fmessenger%2Emsn%2Ecom,sign-in=xxx@hotmail.com,pwd=ppp,lc=1033,id=507,tw=40,ru=http% 3A % 2F %2Fmessenger%2Emsn%2Ecom,ct=1175605256,kpp=1,kv=9,ver=2.1.6000.1,rn=qOzSvE*i,
tpf= 4a 85c 137e4ed067172138425903e6af3/r/n/r/n/End
上面加下划线部分的组成分别为当前登陆的MSN帐号“xxx@hotmail.com”,密码“ppp”,和先前保存的字符串。
S到C HTTP/1.1 200 OK/r/n
Connection: close/r/n
Date: Tue, 03 Apr 2007 13:01:05 GMT/r/n
Server: Microsoft-IIS/6.0/r/n
PPServer: PPV: 30 H: BAYPPLOGN3B37 V: 0/r/n
X-Powered-By: ASP.NET/r/n
Content-Type: text/html; charset=iso-8859-1/r/n
Expires: Tue, 03 Apr 2007 13:00:05 GMT/r/n
Cache-Control: no-cache/r/n
Pragma: no-cache/r/n
P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"/r/n
Set-Cookie: PPAuth=ATH0x3xl*vR*qVG3B!Bg0ety9rc!xWUdjLfUzXvMURrowngxrUNsf1vT0E8j5gebghlA9nTyd1w0Tv7zkjuMqpeno4hVzdctTZNE
xL4tP0tc 2G 5h7yYZ7wlts37b8PTDFsq1nqGbaHToenT!*9wWFVIKY1heDdBricfXbheuggsWbhpwAgTPAcHP8ZJrI80Pk40GMVU$; domain=login.live.com;secure= ;path=/;HTTPOnly= ;version=1/r/n
Set-Cookie: PPLState=1; domain=.live.com;path=/;version=1/r/n
Set-Cookie: MSPVis=507;domain=login.live.com;path=//r/n
Authentication-Info: Passport1.4
da-status=success,from-PP='t=9UFh9dbIiFj8svZSweRD1PEkycFPpomSh3D 0C 0YgrKgqEGDLDj2HeMuV7
bPR99ro1*qXjwJdmDkzbs5UDns5n*gm21tx!y7dVS0ojoS5Hy3XyYkSyw6WhiASIDsJbjpY 9M &p=9EZtFudGvHCmCJ5!loRRpoKPaIqcrz7GglOT4EnvtvGWzpUFc7as1xnk3Ya7YzaQ0fqmEGLIgM05w*
8i6nHn3KoGVBhFtnPYwCK2N!pTQDvO*RkrfAuQnwkGR!zXrcM0LEWpRkzCWwnSl6VG7an7rYbQuL1eg9wJ8Hn!D1r!j2izE92Xv0uRuQTw$$',ru=http://messenger.msn.com
Content-Length: 0/r/n/r/n/End
保存上面加下划线的字符串,断开当前的SSL连接,转到先前保留的与通知服务器的连接,执行下面步骤。
C到S USR 7 TWN S
t=9UFh9dbIiFj8svZSweRD1PEkycFPpomSh3D 0C 0YgrKgqEGDLDj2HeMuV
7bPR99ro1*qXjwJdmDkzbs5UDns5n*gm21tx!y7dVS0ojoS5Hy3XyYkSyw6WhiASIDsJbjpY 9M &p=9EZtFudGvHCmCJ5!loRRpoKPaIqcrz7GglOT4EnvtvGWzpUFc7as1xnk3Ya7YzaQ0fqmEGL
IgM05w*8i6nHn3KoGVBhFtnPYwCK2N!pTQDvO*RkrfAuQnwkGR!zXrcM0LEWpRkzCWwnSl6VG7an7rYbQuL1eg9wJ8Hn!D1r!j2izE92Xv0uRuQTw$$/r/n/End
加下划线部分为刚刚保存的字符串。
S到C USR 7 OK xxx@hotmail.com 1 0/r/n
SBS 0 null/r/n
MSG Hotmail Hotmail 531/r/n
MIME-Version: 1.0/r/n
Content-Type: text/x-msmsgsprofile; charset=UTF-8/r/n
LoginTime: 1175605266/r/n
EmailEnabled: 1/r/n
MemberIdHigh: 409600/r/n
MemberIdLow: -1798698030/r/n
lang_preference: 2052/r/n
preferredEmail: /r/n
country: CN/r/n
PostalCode: /r/n
Gender: /r/n
Kid: 0/r/n
Age: /r/n
BDayPre: /r/n
Birthday: /r/n
Wallet: /r/n
Flags: 1073742915/r/n
sid: 507/r/n
MSPAuth: 9UFh9dbIiFj8svZSweRD1PEkycFPpomSh3D 0C 0YgrKgqEGDLDj2He
MuV7bPR99ro1*qXjwJdmDkzbs5UDns5n*gm21tx!y7dVS0ojoS5Hy3XyYkSyw6WhiASIDsJbjpY 9M /r/n
ClientIP: 58.62.100.239/r/n
ClientPort: 28267/r/n
ABCHMigrated: 1/r/n
Nickname: qq/r/n/r/n/End
到此登陆成功,必须保存加下划线部分,其他的可以依据自己的需要选择保存。最终我们一定保存的是与通知服务器3的连接和最后的加下划线部分4。
对https://contacts.msn.com/abservice/abservice.asmx 作一次安全HTTP请求,请
求前注意设置方法为POST,和下面几个头
(一) SOAPAction:http://www.msn.com/webservices/AddressBook/ABFindAll
(二) Content-Type:text/xml; charset=utf-8
(三) Cookie: MSPAuth=cookie
发送的实体为一个XML5。
最终服务器返回一个包含联系人详细信息的XML6。对该XML进行解析获取自己所需的信息。
3. 向NS注册详细人和改变自己的登陆状态
转换到NS连接。
C到S ADL 8 68/r/n
<ml l="1"><d n="hotmail.com"><c n="yyy" l="37" t="1" /></d></ml>/End
加下划线部分为好友的帐号yyy@hotmail.com的拆分。
S到C ADL 8 OK/r/n/End
C到S CHG 9 BRB/r/n/End
改变自己的状态为BRB8
S到C CHG 9 BRB 0/r/n
S到C ILN 9 NLN yyy@hotmail.com yyy@hotmail.com 0/r/n/End
获得所有在你改变状态前已经在线的好友。
转换到NS连接。
C到S XFR 10 SB/r/n/End
S到C XFR 10 SB 207.46.26.58:1863 CKI 928864133.1051549.14342115 U
messenger.msn.com/r/n/End
得到中转服务器的IP和端口,还有验证串,如上加下划线部分。保留NS连接,重新建立一个连接到中转服务器207.46.26.58的1863端口,执行下面步骤。
C到S USR 1 xxx@hotmail.com 928864133.1051549.14342115/r/n/End
S到C USR 1 OK xxx@hotmail.com xxx@hotmail.com/r/n/End
C到S CAL 2 yyy@hotmail.com/r/n/End
S到C CAL 2 RINGING 928864133/r/n
S到C JOI yyy@hotmail.com yyy@hotmail.com 0/r/n/End
至此好友yyy@hotmail.com已经加入该对话中了,接下来向其发送Hello。
C到S MSG 3 N 67/r/n
MIME-Version: 1.0/r/n
Content-Type: text/plain; charset=UTF-8/r/n
/r/n
Hello/End
监听NS连接。
S到C RNG 1383157243 207.46.26.58:1863 CKI 14613584.781244 yyy@hotmail.com
yyy@hotmail.com U messenger.msn.com/r/n/End
得到中转服务器的IP和端口,还有两个验证串,如上加下划线部分。保留NS连接,重新建立一个连接到中转服务器207.46.26.58的1863端口,执行下面步骤。
C到S ANS 1 xxx@hotmail.com 14613584.781244 1383157243/r/n/End
S到C IRO 1 1 1 yyy@hotmail.com yyy@hotmail.com 0/r/n
至此你已经加入该对话中,紧跟着接收好友yyy@hotmail.com发送来的Hello。
S到C MSG yyy@hotmail.com yyy@hotmail.com 67/r/n
MIME-Version: 1.0/r/n
Content-Type: text/plain; charset=UTF-8/r/n
/r/n
Hello/End
1. 有latex和mml源码的静态数学公式
/int_0^a/int_2^5(x*y)dxdy
<math>
<mstyle>
<mrow>
<msubsup>
<mo>∫</mo>
<mn>0</mn>
<mi>a</mi>
</msubsup>
</mrow>
<mrow>
<msubsup>
<mo>∫</mo>
<mn>2</mn>
<mn>5</mn>
</msubsup>
</mrow>
<mrow>
<mo>(</mo>
<mi>x</mi>
<mo>⋅</mo>
<mi>y</mi>
<mo>)</mo>
</mrow>
<mrow>
<mi>d</mi>
<mi>x</mi>
</mrow>
<mrow>
<mi>d</mi>
<mi>y</mi>
</mrow>
</mstyle>
</math>
/lim_{n /to /infty}x_n
<math>
<mstyle>
<munder>
<mo>lim</mo>
<mrow>
<mi>n</mi>
<mo>→</mo>
<mo>∞</mo>
</mrow>
</munder>
<msub>
<mi>x</mi>
<mi>n</mi>
</msub>
</mstyle>
</math>
/bar{q} /to p
<math>
<mstyle>
<mover>
<mrow>
<mi>q</mi>
</mrow>
<mo>¯</mo>
</mover>
<mo>→</mo>
<mi>p</mi>
</mstyle>
</math>
2. 只有mml源码的动态数学公式
<math>
<maction actiontype="toggle" selection="1">
<mrow>
<msup>
<mi>x</mi>
<mn>2</mn>
</msup>
<mo>+</mo>
<mi>x</mi>
<mo>+</mo>
<mn>5</mn>
<mo>=</mo>
<mn>0</mn>
</mrow>
<mrow>
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow>
<mo>-</mo>
<mn>1</mn>
<mo>±</mo>
<mi>i</mi>
<mo>⁢</mo>
<msqrt>
<mn>19</mn>
</msqrt>
</mrow>
<mn>2</mn>
</mfrac>
</mrow>
</maction>
</math>
<math>
<maction actiontype="tooltip">
<mrow>
<msup>
<mi>x</mi>
<mn>2</mn>
</msup>
<mo>+</mo>
<mi>x</mi>
<mo>+</mo>
<mn>5</mn>
<mo>=</mo>
<mn>0</mn>
</mrow>
<mtext>方程于复数域有解</mtext>
</maction>
</math>
wtc.discourse.Main类:
系统的主类,该类启动SimpleHTTP服务器,和调出登陆界面。
wtc.discourse. Base类:
系统的基础类,包括一些主要数据的保存,如:系统的根目录,系统SimpleHTTP的网址导向数组等。
wtc.discourse.simplehttp. SimpleHTTP类:
启动一个本地的简单代理HTTP服务端,只服务一个客户端——系统的表现层。
wtc.discourse.simplehttp. OneResponse类:
对于每一个HTTP请求进行分析处理并返回对应的数据,依靠wtc.discourse. Base类的网址导向数组进行导向。
wtc.discourse.Authorization类:
对登陆进行统一处理。该类中主要函数有:
public void set(String accounts, String password, int index) {
this.accountsJCB.setSelectedItem(accounts);
this.passJPF.setText(password);
this.statusJCB.setSelectedIndex(index);
}
该函数执行对登陆帐号、密码和状态的设置,之后调用下列函数进行登陆操作。
boolean login() {
char[] pass = this.passJPF.getPassword();
if (pass == null) {
return false;
}
String accounts = ((String) accountsJCB.getSelectedItem()).trim();
if (accounts == null || accounts.equals("") ||
accounts.indexOf('@') < 0) {
return false;
}
statusbarJL.setText("连接服务器...");
Login l = new Login(accounts, new String(pass).trim());
String result = l.login();
if (result == null) {
return false;
}
//保存一下我登陆后的反馈信息
statusbarJL.setText("保存一下我登陆后的反馈信息...");
Initial initial = Initial.getInitial();
MyInfo mi = new MyInfo(result);
if (initial == null || mi == null || mi.values[0] == null) {
return false;
}
mi.myPassport = accounts;
initial.myInfo = mi;
//守候服务器的信息
statusbarJL.setText("启动本地服务...");
WaitNSin wni = new WaitNSin();
wni.start();
//获取联系人列表
statusbarJL.setText("获取联系人列表...");
ContactList cl = new ContactList();
ContactListData cld = cl.getAllAB(mi.getCookie());
if (cld == null) {
return false;
}
//向NS注册自己的联系列表并返回我的格式的联系人xml
statusbarJL.setText("向NS注册自己的联系列...");
synchronized (Base.giveBrowse) {
Base.giveBrowse = cl.putListToNSandReturnXMLAB(cld) +
Base.giveBrowse;
}
return true;
}
该函数于登陆成功时返回true,否则返回false。
wtc.io. BufferedReader类:
对一个输入流进行封装,以让其适应有效载荷方式的输入,允许读入一行数据或者读入指定数量的字节。
wtc.one. OneHTTP类:
对一个HTTP请求进行封装,允许将一个HTTP或者HTTPS请求的有效数据做为一串字符返回或者作为一个文档返回。
wtc.discourse.msn. Initial类:
wtc. discourse.msn包中的基础类,包括一些外部xml文件的名称,输入输出的统一编码方式,当前登陆用户基本信息的保存内存地址等。
wtc.discourse.msn. MyInfo类:
该类保存当前登陆用户的基本信息,包括:昵称、登陆时间、认证串等。
public String getCookie() {
return this.flags[this.mspAuth] + "=" + this.values[this.mspAuth];
}
返回基于SOAP9的HTTP请求时必须的cookie10。
wtc.discourse.msn. SocketStream类:
持久保存与NS服务器的连接,并对向NS的信息输出进行封装,如下函数:
public void nsOut(String sendS) {
try {
byte buf[] = sendS.getBytes(Initial.getInitial().encode_out);
this.nsos.write(buf, 0, buf.length);
this.nsos.flush();
Log.getDefault().log("C到S " + sendS);
} catch (Exception ex) {
if (debug) {
ex.printStackTrace();
}
}
}
wtc.discourse.msn. ContactList类:
该类对好友列表信息的获取、转换、和向NS服务器的登记的操作进行封装。
wtc.discourse.msn. ChangeStatus类:
对改变当前登陆用户的状态操作进行封装,登陆成功后必须紧跟着通过以下代码进行
状态的改变。
new ChangeStatus().changeStatus(status[statusJCB. getSelectedIndex()]);
一般的改变状态方式为:
ChangeStatus cs = new ChangeStatus();
cs.changeStatus(cs.在线);
wtc.discourse.msn. WaitNSin类:
对NS服务器的输入信息进行守候,并调用相应的模块进行响应。
wtc.discourse.msn. Switchboard类:
代表一个与SB服务器的连接,封装内容为上述MSN协议的发送和接收部分。
wtc.discourse.msn. WaitSSin类:
对SB服务器的输入信息进行守候,并调用相应的模块进行响应。
wtc.discourse.msn.command. Commands接口:
包含了所有用到的MSN命令。
wtc.discourse.msn.login. Login类:
封装了msn协议的登陆部分。常用用法为:
Login l = new Login(帐号,密码);
String result = l.login();
wtc.discourse.msn.login. Authorization类:
封装了msn协议登陆时要通过SSL连接验证的部分,一般由wtc.discourse.msn.login. Login类创建。
<script type="text/javascript"> google_ad_client = "pub-5033576919944123"; google_ad_width = 728; google_ad_height = 90; google_ad_format = "728x90_as"; google_ad_type = "text_image"; //2007-10-24: csdn.blog google_ad_channel = "8548491739"; </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>