09-05-2010, 01:03 +0200
Forum: Overviewworkscript announcements
Basic msn client in Tcl
AuthorPost
HackeMate  05-09-2008, 12:55   | Example to connect Msn      Quote  Reply
Member since 05/2008
6 Posts
Location: Spain
This is not a final script to use msn, it just contain the basic part for log in, the else of work only requires read the msn commands. The comments are based in http://www.hypothetic.org/docs/msn/, my English is not so good :)

1  #!/usr/bin/tclsh
2  #
3  # This is an elemental Msn client using the protocol MSNP8 (windows messenger default)
4  # Not third-party client. It's an example for your information.
5  # Written by HackeMate @ QuakeNet
6  #            Sentencia @ IRC-Hispano
7  # Sentencia@librepensamiento.es
8  
9  proc msn:sdata {sock str} {
10     puts $sock "$str"
11     msn:echo "*** $sock: $str"
12  }
13  
14  proc msn:echo {str} {
15    
16     switch -- [string range $str 0 3] {
17        "::: " {
18       set prefix "Msn:>"
19       set str [string range $str 4 end]
20        }
21        "*** " {
22          set prefix "02Sending:\>02"
23       set str [string range $str 4 end]
24        }
25        "!!! " {
26       set prefix "2Incomming ERROR:02"
27       set str [string rane $str 4 end]
28        }
29        "default" {
30       set prefix "Incomming data:"
31        }
32     }
33     puts stdout "$prefix $str"
34  }
35    
36  proc msn:nexus {} {
37  
38     # Passport authentication begins with the passport nexus, just as logging into messenger begins with the Dispatch Server
39     # Using secure http request to the next path.
40    
41     package require http
42     package require tls
43     http::register https 443 ::tls::socket
44    
45     set token [http::geturl https://nexus.passport.com/rdr/pprdr.asp]
46     upvar #0 $token state
47     foreach {name value} $state(meta) {
48        if {$name == "PassportURLs"} {
49          set data [split $value ","]
50             set dalogin [lsearch -all -inline $data "DALogin=*"]
51       set dalogin [lindex [split $dalogin "="] 1]
52       msn:echo "::: PassPort saved. We are jumping to $dalogin"
53       msn:passport $dalogin
54       return
55        }
56     }
57  
58     # I admit that this is a dirty way to know when passort auth was failed.
59     # Sorry about, I'm lazy.  
60     msn:echo "!!! Authentication process was not good."
61     close $::msn(sock)
62     # This exist command will exit from the previous command executed in msn:Login vwait forever
63     exit
64     return
65  }
66  
67  proc msn:passport {url} {
68    
69     # The client sends a https get request for the url given to it by the nexus (saved in $dalogin, here $url)
70     # The login is waiting the last parameters that we saved in $::msn(auth), like a header.
71    
72     package require http
73     package require tls
74     http::register https 443 ::tls::socket
75  
76     set url "https://$url"
77     set account [string map [list "\@" "\%40"] $::msn(account)]
78     set token [http::geturl $url -headers [list Authorization "Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=$account,pwd=$::msn(password),$::msn(auth)"]]
79     upvar #0 $token state
80    
81     # If we fail the authentication, instead HTTP 200 it will return something like HTTP 302, or if
82     # the syntax was badly, HTTP 401. If all is Ok, this foreach will connect us.
83    
84     foreach {name value} $state(meta) {
85        if {$name == "Authentication-Info"} {
86       regexp {\'(.*?)\'} $value "" cookie
87       incr ::msn(trid)
88       msn:sdata $::msn(sock) "USR $::msn(trid) TWN S $cookie"
89        }
90     }
91  }
92  # Configuration
93  
94  set ::msn(account) "Your@Messenger.account"
95  set ::msn(password) "AGoodPassword"
96  
97  # We define here the version protocol.
98  # This variable will be used only twice.
99  
100  set ::msn(version) "MSNP8 CVR0"
101  
102  # (CVR) The CVR command sends version information about a client and operating
103  # system to the server. For the official client, the server will reply with
104  # information about a recommended version of the client. It's debatable whether
105  # third-party clients should send CVR. Microsoft might start blocking users based on
106  # this command, or they might tread third-party clients better than now if there was
107  # evidence that a significant number of people used them. Any way, Microsoft
108  # has no way to verify the information given.
109  
110  # Independently of all this debat, Where are you from? :) Spanish location is 0x0C0A
111  # American users send: 0x0409
112  # For your information: http://www.microsoft.com/globaldev/reference/oslocversion.mspx
113  # This var may define your Locale configuration
114  set ::msn(location) "0x0C0A"
115  
116  # This is our info. It is what a Windows XP & windows messenger sends.
117  
118  set ::msn(msnms) "winnt 5.1 i386 MSMSGS 4.7.3001 WindowsMessenger"
119  
120  
121  # End of parameters.
122  
123  # We are going
124  
125  proc msn:Login { { server "messenger.hotmail.com" } {port 1863} } {
126    
127     # (TrID) The Transaction IDs, abbreviated as TriDs, are used to much a client command with a server
128     # response. Commands sent by the client are required to contain a TrID, and commands from the server
129     # sent in direct response to that command will contain the same TrID (with some exception).
130     # Every TrID is a number between 0 and 4294967295. Using this TrID wrongly may cause confusion and
131     # server and client will be unstable.
132    
133     if {![info exists ::msn(trid)]} { set ::msn(trid) 1 }
134    
135     # Easy to make multi-server, almost all depend of this (and previous) var name.
136  
137     set ::msn(sock) [socket $server $port]
138     msn:echo "::: Trying to connect $server:$port- sockname: $::msn(sock)"
139    
140     # Because we can receive data in any moment, we need read it as fast as we can, that's why I used
141     # -buffering line instead full. In certain moment negotiating the connection, the socket can get
142     # stuned or we are forced to execute manually gets, if you don't use vwait forever command.
143     # I had bad experiencies with this command in x-chat.
144    
145     fconfigure $::msn(sock) -buffering line -blocking no
146    
147     fileevent $::msn(sock) readable [list msn:gdata $::msn(sock)]
148     msn:sdata $::msn(sock) "VER $::msn(trid) $::msn(version)"
149     vwait forever  
150  }
151  
152  proc msn:gdata {socket} {
153    
154     if {[eof $socket]} {
155        msn:echo "::: Closed connection."
156        close $socket
157        exit
158        return
159     }
160     set datos [gets $socket] 
161     foreach data [split $datos \n] {
162        msn:echo "$data"     
163        if {$data == "VER $::msn(trid) $::msn(version)"} {
164       incr ::msn(trid)
165       msn:sdata $::msn(sock) "CVR $::msn(trid) $::msn(location) $::msn(msnms) $::msn(account)"
166        }
167       
168        set cvr [join [lrange [split $data] 0 1]]
169        if {$cvr == "CVR $::msn(trid)"} {
170       incr ::msn(trid)
171       msn:sdata $::msn(sock) "USR $::msn(trid) TWN I $::msn(account)"
172        }
173       
174        set usr [join [lrange [split $data] 0 3]]
175        if {$usr == "USR $::msn(trid) TWN S"} {
176      
177       # Rude way to save this parameters...
178       # Thanks thommey for advice to use a foreach loop
179       # It will work, I will change it soon
180       set udata [split $data ","]
181       set lc [lsearch -all -inline $udata "lc=*"]
182       set lc [lindex [split $lc "="] 1]
183       set id [lsearch -all -inline $udata "id=*"]
184       set id [lindex [split $id "="] 1]
185       set tw [lsearch -all -inline $udata "tw=*"]
186       set tw [lindex [split $tw "="] 1]
187       set ru [lsearch -all -inline $udata "ru=*"]
188       set ru [lindex [split $ru "="] 1]
189       set ct [lindex [lsearch -all -inline $udata "*ct=*"] 0]
190       set ct [lindex [split $ct] 4]
191       set ct [lindex [split $ct "="] 1]
192       set kpp [lsearch -all -inline $udata "kpp=*"]
193       set kpp [lindex [split $kpp "="] 1]
194       set kv [lsearch -all -inline $udata "kv=*"]
195       set kv [lindex [split $kv "="] 1]
196       set ver [lsearch -all -inline $udata "ver=*"]
197       set ver [lindex [split $ver "="] 1]
198       set rn [lsearch -all -inline $udata "rn=*"]
199       set rn [lindex [split $rn "="] 1]
200       set tpf [lsearch -all -inline $udata "tpf=*"]
201       set tpf [lindex [split $tpf "="] 1]
202       set ::msn(auth) "lc=$lc,id=$id,tw=$tw,ru=$ru,ct=$ct,kpp=$kpp,kv=$kv,ver=$ver,rn=$rn,tpf=$tpf"
203       msn:nexus    
204        }
205       
206        if {$data == "USR $::msn(trid) OK $::msn(account) $::msn(account) 1 0"} {
207       msn:echo "::: Now we are logged in."
208       # This command will mark us as connected for else people.
209       msn:sdata $::msn(sock) "SYN 8 0"
210        }
211        # SYN command will return our buddy list     
212        if {[join [lrange [split $data] 0 1]] == "SYN 8"} {
213       msn:sdata $::msn(sock) "CHG 9 NLN 0"
214        }
215        if {[lindex [split $data] 0] == "ClientIP:"} {
216       set ::msn(selfip) [lindex [split $data] 1]
217        }
218       
219        if {[lindex [split $data] 1] == "ClientPort:"} {
220       set ::msn(selfport) [lindex [split $data] 1]
221       msn:echo "Our IP is: $::msn(selfip) and the port: $::msn(selfport)"
222       msn:sdata "SYN 8 0"
223        }
224       
225        if {[lindex [split $data] 0] == "XFR"} {
226       close $::msn(sock)
227       set server [lindex [split $data] 3]
228       set port [lindex [split $server ":"] 1]
229       set server [lindex [split $server ":"] 0]
230       incr ::msn(trid)
231       msn:Login $server $port
232        }
233       
234        # Catching errors (this is just a few list of)
235       
236        set cmd [lindex [split $data] 0]
237        set cparm [lindex [split $data] 1]
238        switch -- $cmd {
239       "710" {
240          msn:echo "!!! Bad CVR parameters sent."
241       }
242       "711" {
243          msn:echo "!!! Write is blocking."
244       }
245       "712" {
246          msn:echo "!!! Session is overloaded."
247       }
248       "713" {
249          msn:echo "!!! Calling too rapidly. This occurs when the client repeatedly calls someone who is offline or blocking them"
250          msn:echo "!!! in response to the commands that the server rejects. This is a way to know who is blocking you."
251       }
252       "714" {
253          msn:echo "!!! Too many sessions."
254       }
255       "715" {
256          if {$cparm == "30"} {
257                msn:echo "!!! PRP setting an invalid phone type of three or less characters."
258          }
259          if {$cparm == "31"} {
260             msn:echo "!!! ERROR- Changing display name (REA) on an unverified Passport account."
261          }
262       }
263       "731" {
264          msn:echo "!!! ERROR- Not expected. Bad formatted CVR."
265          close $::msn(sock)
266          return
267       }
268        }
269     }
270  }
271  
272  puts stdout "Msn Client loaded"

I'm the Player2
This post was edited 1 times, last on 06-04-2008, 00:24 by HackeMate
Advanced options for this topic:

Ignore this topic (Do not list this topic in the "unread topics" search. You are currently not ignoring this topic.)
Hide this topic (Hidden topics are not displayed in the topics list. This topic is currently not hidden.)
Go to forum

Unclassified NewsBoard 1.5.3-d | © 2003-4 by Yves Goergen