~ubuntu-branches/ubuntu/gutsy/amsn/gutsy

« back to all changes in this revision

Viewing changes to msnp2p.tcl

  • Committer: Bazaar Package Importer
  • Author(s): Theodore Karkoulis
  • Date: 2006-01-04 15:26:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104152602-ipe1yg00rl3nlklv
Tags: 0.95-1
New Upstream Release (closes: #345052, #278575).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
::snit::type P2PMessage {
 
2
 
 
3
        option -sessionid
 
4
        option -identifier
 
5
        option -offset
 
6
        option -totalsize
 
7
        option -datalength
 
8
        option -flag
 
9
        option -ackid
 
10
        option -ackuid
 
11
        option -acksize
 
12
        variable headers
 
13
        variable body ""
 
14
 
 
15
        constructor {args} {
 
16
                #TODO: remove me when object is destroyed in the right place
 
17
                after 30000 $self destroy
 
18
        }
 
19
 
 
20
        #creates a P2PMessage object from a normal Message object
 
21
        method createFromMessage { message } {
 
22
                #               array set headers [$message getHeaders]
 
23
                #               set data [$message getBody]
 
24
                #               set idx [string first "\r\n\r\n" $data]
 
25
                #               set head [string range $data 0 [expr $idx -1]]
 
26
                ##              set body [string range $data [expr $idx +4] end]
 
27
                set body [$message getBody]
 
28
                #               set head [string map {"\r" ""} $head]
 
29
                #               set heads [split $head "\n"]
 
30
                #               foreach header $heads {
 
31
                #                       set idx [string first ": " $header]
 
32
                #                       array set headers [list [string range $header 0 [expr $idx -1]] \
 
33
                    #                                     [string range $header [expr $idx +2] end]]
 
34
                #               }
 
35
                binary scan [string range $body 0 48] iiiiiiiiiiii cSid cId cOffset1 cOffset2 cTotalDataSize1 cTotalDataSize2 cMsgSize cFlags cAckId cAckUID cAckSize1 cAckSize2
 
36
                set body [string range $body 48 end]
 
37
                set options(-sessionid) $cSid
 
38
                set options(-identifier) $cId
 
39
                set options(-offset) [int2word $cOffset1 $cOffset2]
 
40
                set options(-totalsize) [int2word $cTotalDataSize1 $cTotalDataSize2]
 
41
                set options(-datalength) $cMsgSize
 
42
                set options(-flag) $cFlags
 
43
                set options(-ackid) $cAckId
 
44
                set options(-ackuid) $cAckUID
 
45
                set options(-acksize) [int2word $cAckSize1 $cAckSize2]
 
46
        }
 
47
 
 
48
        method toString { {humanReadable 0} } {
 
49
                set str ""
 
50
                foreach { header info } [array get headers] {
 
51
                        set str "$str$header: $info\r\n"
 
52
                }
 
53
                set str "$str\r\n\r\n"
 
54
                if { $humanReadable } {
 
55
                        set str "${str}sessionid: $options(-sessionid)\n"
 
56
                        set str "${str}identifier: $options(-identifier)\n"
 
57
                        set str "${str}offset: $options(-offset)\n"
 
58
                        set str "${str}totalsize: $options(-totalsize)\n"
 
59
                        set str "${str}datalength: $options(-datalength)\n"
 
60
                        set str "${str}flag: $options(-flag)\n"
 
61
                        set str "${str}ackid: $options(-ackid)\n"
 
62
                        set str "${str}ackuid: $options(-ackuid)\n"
 
63
                        set str "${str}acksize: $options(-acksize)\n"
 
64
                } else {
 
65
                        #TODO
 
66
                }
 
67
                set str "$str$body"
 
68
                return $str
 
69
        }
 
70
 
 
71
 
 
72
        #       proc ReadData { message chatid } {
 
73
        #               variable chunkedData
 
74
        #               # Get values from the header
 
75
        ##              set idx [expr [string first "\r\n\r\n" $data] + 4]
 
76
        ##              set headend [expr $idx + 48]
 
77
        #               set data [$message getBody]
 
78
        #
 
79
        #               binary scan [string range $data 0 48] iiiiiiiiiiii cSid cId cOffset1 cOffset2 cTotalDataSize1 cTotalDataSize2 cMsgSize cFlags cAckId cAckUID cAckSize1 cAckSize2
 
80
        #
 
81
        #               set cOffset [int2word $cOffset1 $cOffset2]
 
82
        #               set cTotalDataSize [int2word $cTotalDataSize1 $cTotalDataSize2]
 
83
        #               set cAckSize [int2word $cAckSize1 $cAckSize2]
 
84
        #
 
85
        #               #status_log "Read header : $cSid $cId $cOffset $cTotalDataSize $cMsgSize $cFlags $cAckId $cAckUID $cAckSize\n" red
 
86
        #               #status_log "Sid : $cSid -> " red
 
87
        #
 
88
        #               if {$cSid == "0" && $cMsgSize != "0" && $cMsgSize != $cTotalDataSize } {
 
89
        #
 
90
        #                       if { ![info exists chunkedData($cId)] } {
 
91
        #                               set chunkedData($cId) "[string range $data 48 end-4]"
 
92
        #                       } else {
 
93
        #                               set chunkedData($cId) "$chunkedData($cId)[string range $data 48 end-4]"
 
94
        #                       }
 
95
        #                       #status_log "Data is now : $chunkedData($cId)\n\n";
 
96
        #
 
97
        #                       if { $cTotalDataSize != [string length $chunkedData($cId)] } {
 
98
        #                               return
 
99
        #                       } else {
 
100
        #                               set data $chunkedData($cId)
 
101
        #                               set headend 0
 
102
        #                               set cMsgSize $cTotalDataSize
 
103
        #                       }
 
104
        #
 
105
        #               }
 
106
        #       }
 
107
 
 
108
 
 
109
 
 
110
 
 
111
 
 
112
 
 
113
 
 
114
 
 
115
        method getBody { } {
 
116
                return $body
 
117
        }
 
118
 
 
119
        method getHeader { name } {
 
120
                return [lindex [array get headers $name] 1]
 
121
        }
 
122
}
 
123
 
 
124
namespace eval ::MSNP2P {
 
125
        namespace export loadUserPic SessionList ReadData MakePacket MakeACK MakeSLP
 
126
 
 
127
 
 
128
        #Get picture from $user, if cached, or sets image as "loading", and request it
 
129
        #using MSNP2P
 
130
        proc loadUserPic { chatid user {reload "0"} } {
 
131
                if { [::config::getKey getdisppic] != 1 } {
 
132
                        status_log "Display Pics disabled, exiting loadUserPic\n" red
 
133
                        return
 
134
                }
 
135
 
 
136
                #status_log "::MSNP2P::GetUser: Checking if picture for user $user exists\n" blue
 
137
 
 
138
                set msnobj [::abook::getVolatileData $user msnobj]
 
139
 
 
140
                #status_log "::MSNP2P::GetUser: MSNOBJ is $msnobj\n" blue
 
141
 
 
142
                #set filename [::MSNP2P::GetFilenameFromMSNOBJ $msnobj]
 
143
                set filename [::abook::getContactData $user displaypicfile ""]
 
144
                status_log "::MSNP2P::GetUser: filename is $filename\n" white
 
145
 
 
146
                if { $filename == "" } {
 
147
                        return
 
148
                }
 
149
 
 
150
                global HOME
 
151
                #Reload 1 means that we force aMSN to reload a new display pic
 
152
                #Destroy it before to avoid TkCxImage to redraw animated gif above the good display pic
 
153
                destroy user_pic_$user
 
154
                if { ![file readable "[file join $HOME displaypic cache ${filename}].png"] || $reload == "1" } {
 
155
                        status_log "::MSNP2P::GetUser: FILE [file join $HOME displaypic cache ${filename}] doesn't exist!!\n" white
 
156
                        image create photo user_pic_$user -file [::skin::GetSkinFile "displaypic" "loading.gif"] -format cximage
 
157
 
 
158
                        create_dir [file join $HOME displaypic]
 
159
                        create_dir [file join $HOME displaypic cache]
 
160
                        ::MSNP2P::RequestObject $chatid $user $msnobj
 
161
                } else {
 
162
                        catch {image create photo user_pic_$user -file "[file join $HOME displaypic cache ${filename}].png" -format cximage}
 
163
 
 
164
                }
 
165
        }
 
166
 
 
167
        proc loadUserSmiley { chatid user msnobj } {
 
168
 
 
169
                set filename [::MSNP2P::GetFilenameFromMSNOBJ $msnobj]
 
170
 
 
171
                status_log "Got filename $filename for $chatid with $user and $msnobj\n" red
 
172
 
 
173
                if { $filename == "" } {
 
174
                        return
 
175
                }
 
176
 
 
177
                image create photo custom_smiley_$filename -width 19 -height 19
 
178
 
 
179
                status_log "::MSNP2P::GetUserPic: filename is $filename\n" white
 
180
 
 
181
 
 
182
                global HOME
 
183
                if { [catch {image create photo custom_smiley_$filename -file "[file join $HOME smileys cache ${filename}].png" -format cximage}] } {
 
184
                        #We didn't manage to load the smiley (either we haven't it either it's bad) so we ask it
 
185
                        status_log "::MSNP2P::GetUser: FILE [file join $HOME smileys cache ${filename}] doesn't exist!!\n" white
 
186
                        image create photo custom_smiley_$filename -width 19 -height 19
 
187
 
 
188
                        create_dir [file join $HOME smileys]
 
189
                        create_dir [file join $HOME smileys cache]
 
190
                        ::MSNP2P::RequestObject $chatid $user $msnobj
 
191
                }
 
192
        }
 
193
 
 
194
 
 
195
        proc GetFilenameFromMSNOBJ { msnobj } {
 
196
                set sha1d [split $msnobj " "]
 
197
                set idx [lsearch $sha1d "SHA1D=*"]
 
198
                set sha1d [lindex $sha1d $idx]
 
199
                set sha1d [string range $sha1d 7 end-1]
 
200
                if { $sha1d == "" } {
 
201
                        return ""
 
202
                }
 
203
                #return [::md5::md5 $sha1d]
 
204
                binary scan $sha1d h* filename
 
205
                return $filename
 
206
        }
 
207
 
 
208
        proc GetFilenameFromContext { context } {
 
209
                global msnobjcontext
 
210
 
 
211
                set old_msnobj [::base64::decode $context]
 
212
                set msnobj [string range $old_msnobj [string first "<" $old_msnobj] [expr [string first "/>" $old_msnobj] + 1]]
 
213
 
 
214
                status_log "GetFilenameFromContext : $context == $old_msnobj == $msnobj\n[string first "<" $old_msnobj] - [string first "/>"  $old_msnobj]\n\n" red
 
215
                if { [info exists msnobjcontext($msnobj)] } {
 
216
                        status_log "Found filename\n" red
 
217
                        return $msnobjcontext($msnobj)
 
218
                } else {
 
219
                        status_log "Couln't find filename for context \n$context\n = $msnobj --- [array get msnobjcontext] --[info exists msnobjcontext($msnobj)] \n" red
 
220
                        return ""
 
221
                }
 
222
 
 
223
 
 
224
        }
 
225
 
 
226
        #//////////////////////////////////////////////////////////////////////////////
 
227
        # SessionList (action sid [varlist])
 
228
        # Data Structure for MSNP2P Sessions, contains :
 
229
        # 0 - Message Identifier        (msgid)
 
230
        # 1 - TotalDataSize             (totalsize) This variable is only used if sending data in split packets
 
231
        # 2 - Offset                    (offset)
 
232
        # 3 - Destination               (dest)
 
233
        # 4 - Step to run after ack     (AferAck)   For now can be DATAPREP, SENDDATA
 
234
        # 5 - CallID (MSNSLP)           (callid)
 
235
        # 6 - File Descriptor           (fd)
 
236
        # 7 - Session Type              (type) bicon, emoticon, filetransfer
 
237
        # 8 - Filename for transfer     (Filename)
 
238
        # 9 - branchid                  (branchid)
 
239
        #
 
240
        # action can be :
 
241
        #       get : This method returns a list with all the array info, 0 if non existent
 
242
        #       set : This method sets the variables for the given sessionid, takes a list as argument.
 
243
        #       unset : This method removes the given sessionid variables
 
244
        #       findid : This method searches all Sessions for one that has the given Identifier, returns session ID or -1 if not found
 
245
        #       findcallid : This method searches all Sessions for one that has the given Call-ID, returns session ID or -1 if not found
 
246
        proc SessionList { action sid { varlist "" } } {
 
247
 
 
248
                switch $action {
 
249
                        get {
 
250
                                set ret [getObjOption $sid MsgId] 
 
251
                                #status_log "getting $sid : [getObjOption $sid MsgId] - $ret" green
 
252
 
 
253
                                if { $ret != "" } {
 
254
                                        # Session found, return values
 
255
                                        lappend ret [getObjOption $sid TotalSize] 
 
256
                                        lappend ret [getObjOption $sid Offset] 
 
257
                                        lappend ret [getObjOption $sid Destination] 
 
258
                                        lappend ret [getObjOption $sid AfterAck]
 
259
                                        lappend ret [getObjOption $sid CallId] 
 
260
                                        lappend ret [getObjOption $sid Fd]
 
261
                                        lappend ret [getObjOption $sid Type] 
 
262
                                        lappend ret [getObjOption $sid Filename]
 
263
                                        lappend ret [getObjOption $sid branchid]
 
264
 
 
265
                                        #status_log "returning $ret" green
 
266
                                        return $ret
 
267
                                } else {
 
268
                                        #status_log "Not found" green
 
269
                                        # Session not found, return 0
 
270
                                        return 0
 
271
                                }
 
272
                        }
 
273
 
 
274
                        set {
 
275
                                #status_log "setting $sid with $varlist" green
 
276
                                # This overwrites previous vars if they are set to something else than -1
 
277
                                if { [lindex $varlist 0] != -1 } {
 
278
                                        setObjOption $sid MsgId [lindex $varlist 0]
 
279
                                        setObjOption [lindex $varlist 0] sid $sid
 
280
                                }
 
281
                                if { [lindex $varlist 1] != -1 } {
 
282
                                        setObjOption $sid TotalSize [lindex $varlist 1]
 
283
                                }
 
284
                                if { [lindex $varlist 2] != -1 } {
 
285
                                        setObjOption $sid Offset [lindex $varlist 2]
 
286
                                }
 
287
                                if { [lindex $varlist 3] != -1 } {
 
288
                                        setObjOption $sid Destination [lindex $varlist 3]
 
289
                                }
 
290
                                if { [lindex $varlist 4] != -1 } {
 
291
                                        setObjOption $sid AfterAck [lindex $varlist 4]
 
292
                                }
 
293
                                if { [lindex $varlist 5] != -1 } {
 
294
                                        setObjOption $sid CallId [lindex $varlist 5]
 
295
                                        setObjOption [lindex $varlist 5] sid $sid
 
296
                                }
 
297
                                if { [lindex $varlist 6] != -1 } {
 
298
                                        setObjOption $sid Fd [lindex $varlist 6]
 
299
                                }
 
300
                                if { [lindex $varlist 7] != -1 } {
 
301
                                        setObjOption $sid Type [lindex $varlist 7]
 
302
                                }
 
303
                                if { [lindex $varlist 8] != -1 } {
 
304
                                        setObjOption $sid Filename [lindex $varlist 8]
 
305
                                }
 
306
                                if { [lindex $varlist 9] != -1 } {
 
307
                                        setObjOption $sid branchid [lindex $varlist 9]
 
308
                                }
 
309
                        }
 
310
 
 
311
                        unset {
 
312
                                #status_log "unsetting..." green
 
313
                                return
 
314
                        }
 
315
                        findcallid -
 
316
                        findid {
 
317
                                #status_log "Finding $action of $sid, found : [getObjOption $sid sid]" green
 
318
                                if { [getObjOption $sid sid] != "" } {
 
319
                                        return [getObjOption $sid sid]
 
320
                                }
 
321
                        }
 
322
                }
 
323
        }
 
324
 
 
325
 
 
326
        #//////////////////////////////////////////////////////////////////////////////
 
327
        # ReadData ( data chatid )
 
328
        # This is the handler for all received MSNP2P packets
 
329
        # data is the MSNP2P packet
 
330
        # chatid will be used to get the SB ?? Ack alvaro if it's better to use chatid or some way to use the dest email
 
331
        # For now only manages buddy and emoticon transfer
 
332
        # TODO : Error checking on fields (to, from, sizes, etc)
 
333
        proc ReadData { message chatid } {
 
334
                global HOME
 
335
                variable chunkedData
 
336
 
 
337
                #               set message [P2PMessage create %AUTO%]
 
338
                #               $message createFromMessage $msg
 
339
 
 
340
                #status_log "called ReadData with $data\n" red
 
341
 
 
342
                # Get values from the header
 
343
                #               set idx [expr [string first "\r\n\r\n" $data] + 4]
 
344
                #               set headend [expr $idx + 48]
 
345
                #               set data [$message getBody]
 
346
 
 
347
                #               binary scan [string range $data 0 48] iiiiiiiiiiii cSid cId cOffset1 cOffset2 cTotalDataSize1 cTotalDataSize2 cMsgSize cFlags cAckId cAckUID cAckSize1 cAckSize2
 
348
 
 
349
                #               set cOffset [int2word $cOffset1 $cOffset2]
 
350
                #               set cTotalDataSize [int2word $cTotalDataSize1 $cTotalDataSize2]
 
351
                #               set cAckSize [int2word $cAckSize1 $cAckSize2]
 
352
 
 
353
                #status_log "Read header : $cSid $cId $cOffset $cTotalDataSize $cMsgSize $cFlags $cAckId $cAckUID $cAckSize\n" red
 
354
                #status_log "Sid : $cSid -> " red
 
355
 
 
356
                set cSid [$message cget -sessionid]
 
357
                set cId [$message cget -identifier]
 
358
                set cOffset [$message cget -offset]
 
359
                set cTotalDataSize [$message cget -totalsize]
 
360
                set cMsgSize [$message cget -datalength]
 
361
                set cFlags [$message cget -flag]
 
362
                set cAckId [$message cget -ackid]
 
363
                set cAckUID [$message cget -ackuid]
 
364
                set cAckSize [$message cget -acksize]
 
365
                set data [$message getBody]
 
366
 
 
367
                if {$cSid == "0" && $cMsgSize != "0" && $cMsgSize != $cTotalDataSize } {
 
368
 
 
369
                        if { ![info exists chunkedData($cId)] } {
 
370
                                set chunkedData($cId) "[string range $data 0 [expr { $cMsgSize - 1}]]"
 
371
                        } else {
 
372
                                set chunkedData($cId) "$chunkedData($cId)[string range $data 0 [expr { $cMsgSize - 1}]]"
 
373
                        }
 
374
                        #                       status_log "Data is now : $chunkedData($cId)\n\n";
 
375
                        status_log "chunked data :  $cTotalDataSize - $cMsgSize - $cOffset - [string length $chunkedData($cId)]"
 
376
 
 
377
                        if { $cTotalDataSize != [expr $cMsgSize + $cOffset] } {
 
378
                                #       status_log "not enough data to complete chunk...$cTotalDataSize - $cOffset - $cMsgSize - [string length $chunkedData($cId)]" 
 
379
                                return
 
380
                        } else {
 
381
                                #status_log "data completed... $cTotalDataSize - $cOffset - [string length $chunkedData($cId)]"
 
382
                                set data $chunkedData($cId)
 
383
                                #                               set headend 0
 
384
                                set cMsgSize $cTotalDataSize
 
385
                        }
 
386
 
 
387
                }
 
388
 
 
389
                if { [lindex [SessionList get $cSid] 7] == "ignore" } {
 
390
                        status_log "MSNP2P | $cSid -> Ignoring packet! not for us!\n"
 
391
                        return
 
392
                }
 
393
 
 
394
 
 
395
                # Check if this is an ACK Message
 
396
                # TODO : Actually check if the ACK is good ? check size and all that crap...
 
397
                if { $cMsgSize == 0 } {
 
398
 
 
399
                        # Let us check if any of our sessions is waiting for an ACK
 
400
                        set sid [SessionList findid $cAckId]
 
401
                        status_log "GOT SID : $sid for Ackid : $cAckId\n"
 
402
                        if { $sid != -1 } {
 
403
                                #status_log "MSNP2P | $sid -> Got MSNP2P ACK " red
 
404
 
 
405
                                # We found a session id that is waiting for an ACK
 
406
                                set step [lindex [SessionList get $sid] 4]
 
407
 
 
408
                                # Just these 2 for now, will probably need more with file transfers
 
409
                                switch $step {
 
410
                                        DATAPREP {
 
411
                                                # Set the right variables, prepare to send data after next ack
 
412
                                                SessionList set $sid [list -1 4 0 -1 "SENDDATA" -1 -1 -1 -1 -1]
 
413
 
 
414
                                                # We need to send a data preparation message
 
415
                                                SendPacket [::MSN::SBFor $chatid] [MakePacket $sid [binary format i 0]]
 
416
                                                status_log "MSNP2P | $sid -> Sent DATA Preparation\n" red
 
417
                                        }
 
418
                                        SENDDATA {
 
419
                                                #status_log "MSNP2P | $sid -> Sending DATA now\n" red
 
420
                                                set file [lindex [SessionList get $sid] 8]
 
421
                                                if { $file != "" } {
 
422
                                                        SendData $sid $chatid "[lindex [SessionList get $sid] 8]"
 
423
                                                } else {
 
424
                                                        SendData $sid $chatid "[::skin::GetSkinFile displaypic [::config::getKey displaypic]]"
 
425
                                                }
 
426
                                        }
 
427
                                        DATASENT {
 
428
                                                SessionList set $sid [list -1 -1 0 -1 0 -1 -1 -1 -1 -1]
 
429
                                                #status_log "MSNP2P | $sid -> Got ACK for sending data, now sending BYE\n" red
 
430
                                                set branchid "[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]"
 
431
                                                SendPacket [::MSN::SBFor $chatid] [MakePacket $sid [MakeMSNSLP "BYE" [lindex [SessionList get $sid] 3] [::config::getKey login] "$branchid" "0" [lindex [SessionList get $sid] 5] 0 0] 1]
 
432
                                        }
 
433
                                }
 
434
                        }
 
435
                        return
 
436
                }
 
437
                #status_log "ReadData : data : $data"
 
438
                # Check if this is an INVITE message
 
439
                if { [string first "INVITE MSNMSGR" $data] != -1 } {
 
440
                        #status_log "Got an invitation!\n" red
 
441
 
 
442
                        # Let's get the session ID, destination email, branchUID, UID, AppID, Cseq
 
443
                        set idx [expr [string first "SessionID:" $data] + 11]
 
444
                        set idx2 [expr [string first "\r\n" $data $idx] - 1]
 
445
                        set sid [string range $data $idx $idx2]
 
446
 
 
447
                        set idx [expr [string first "From: <msnmsgr:" $data] + 15]
 
448
                        set idx2 [expr [string first "\r\n" $data $idx] - 2]
 
449
                        set dest [string range $data $idx $idx2]
 
450
 
 
451
                        set idx [expr [string first "branch=\{" $data] + 8]
 
452
                        set idx2 [expr [string first "\}" $data $idx] - 1]
 
453
                        set branchuid [string range $data $idx $idx2]
 
454
 
 
455
                        set idx [expr [string first "Call-ID: \{" $data] + 10]
 
456
                        set idx2 [expr [string first "\}" $data $idx] - 1]
 
457
                        set uid [string range $data $idx $idx2]
 
458
 
 
459
                        set idx [expr [string first "CSeq:" $data] + 6]
 
460
                        set idx2 [expr [string first "\r\n" $data $idx] - 1]
 
461
                        set cseq [string range $data $idx $idx2]
 
462
 
 
463
                        set idx [expr [string first "Content-Type: " $data $idx] + 14]
 
464
                        set idx2 [expr [string first "\r\n" $data $idx] - 1]
 
465
                        set ctype [string range $data $idx $idx2]
 
466
 
 
467
                        status_log "Got INVITE with content-type : $ctype\n" red
 
468
 
 
469
                        if { $ctype == "application/x-msnmsgr-transreqbody"} {
 
470
 
 
471
                                set sid [SessionList findcallid $uid]
 
472
                                set type [lindex [SessionList get $sid] 7]
 
473
 
 
474
                                #this catches an error with MSN7, still need to find out why sid = -1
 
475
                                if {$sid == -1} {return}
 
476
                                set idx [expr [string first "Conn-Type: " $data] + 11]
 
477
                                set idx2 [expr [string first "\r\n" $data $idx] - 1]
 
478
                                set conntype [string range $data $idx $idx2]
 
479
 
 
480
                                set idx [expr [string first "UPnPNat: " $data] + 9]
 
481
                                set idx2 [expr [string first "\r\n" $data $idx] - 1]
 
482
                                set upnp [string range $data $idx $idx2]
 
483
 
 
484
                                # Let's send an ACK
 
485
                                SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
486
 
 
487
                                if { $type == "filetransfer" } {
 
488
                                        # We received an invite for a FT, send 200 OK
 
489
                                        ::MSN6FT::answerFTInvite $sid $chatid $branchuid $conntype
 
490
                                } elseif { $type == "webcam" } {
 
491
                                        ::MSNCAM::answerCamInvite $sid $chatid $branchuid
 
492
                                }
 
493
 
 
494
                        } elseif { $ctype == "application/x-msnmsgr-sessionreqbody" } {
 
495
 
 
496
                                # Let's check if it's an invitation for buddy icon or emoticon
 
497
                                set idx [expr [string first "EUF-GUID:" $data] + 11]
 
498
                                set idx2 [expr [string first "\}" $data $idx] - 1]
 
499
                                set eufguid [string range $data $idx $idx2]
 
500
 
 
501
                                set idx [expr [string first "Context:" $data] + 9]
 
502
                                set idx2 [expr [string first "\r\n" $data $idx] - 1]
 
503
                                set context [string range $data $idx $idx2]
 
504
 
 
505
 
 
506
                                if { $eufguid == "A4268EEC-FEC5-49E5-95C3-F126696BDBF6" ||
 
507
                                     $eufguid == "5D3E02AB-6190-11D3-BBBB-00C04F795683" ||
 
508
                                     $eufguid == "E073B06B-636E-45B7-ACA4-6D4B5978C93C" ||
 
509
                                     $eufguid == "4BD96FC0-AB17-4425-A14A-439185962DC8" ||
 
510
                                     $eufguid == "1C9AA97E-9C05-4583-A3BD-908A196F1E92"} {
 
511
                                        status_log "MSNP2P | $sid $dest -> Got INVITE for buddy icon, emoticon, or file transfer, or Wink(MSN 7)\n" red
 
512
                                        # Make new data structure for this session id
 
513
                                        if { $eufguid == "A4268EEC-FEC5-49E5-95C3-F126696BDBF6" } {
 
514
                                                # Buddyicon or emoticon
 
515
                                                if { [GetFilenameFromContext $context] != "" } {
 
516
                                                        SessionList set $sid [list 0 0 0 $dest 0 $uid 0 "bicon" [GetFilenameFromContext $context] ""]
 
517
                                                } else {
 
518
                                                        status_log "MSNP2P | $sid -> This is not an invitation for us, don't reply.\n" red
 
519
                                                        # Now we tell this procedure to ignore all packets with this sid
 
520
                                                        SessionList set $sid [list 0 0 0 0 0 0 0 "ignore" 0 ""]
 
521
                                                        return
 
522
                                                }
 
523
                                        } elseif { $eufguid == "5D3E02AB-6190-11D3-BBBB-00C04F795683" } {
 
524
                                                # File transfer
 
525
                                                #check if a conversation is open with that contact
 
526
                                                #no need to test either a chatwindow has been created or not, because MakeFor is going to do it ! 
 
527
                                                ::ChatWindow::MakeFor $chatid
 
528
                                                SessionList set $sid [list 0 0 0 $dest 0 $uid 0 "filetransfer" "" "$branchuid"]
 
529
                                                # Let's send an ACK
 
530
                                                SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
531
                                                status_log "MSNP2P | $sid $dest -> Sent ACK for INVITE\n" red
 
532
 
 
533
                                                # Let's get filename and filesize from context
 
534
                                                set idx [expr [string first "Context:" $data] + 9]
 
535
                                                set context [base64::decode [string range $data $idx end]]
 
536
                                                ::MSN6FT::GotFileTransferRequest $chatid $dest $branchuid $cseq $uid $sid $context
 
537
                                                return
 
538
 
 
539
                                        } elseif { $eufguid =="E073B06B-636E-45B7-ACA4-6D4B5978C93C"} {
 
540
                                                #We received Winks
 
541
                                                status_log "####WINKS RECEIVED####\n" blue
 
542
                                                set decoding [base64::decode $context]
 
543
                                                status_log "$decoding\n" blue
 
544
                                                status_log "######################\n" blue
 
545
 
 
546
                                                # Let's notify the user that he/she has received a Wink
 
547
                                                SendMessageFIFO [list ::amsn::WinWrite $chatid "\n [trans winkreceived [::abook::getDisplayNick $chatid]]\n" black "" 0] "::amsn::messages_stack($chatid)" "::amsn::messages_flushing($chatid)"
 
548
                                        } elseif { $eufguid == "4BD96FC0-AB17-4425-A14A-439185962DC8" ||
 
549
                                                   $eufguid == "1C9AA97E-9C05-4583-A3BD-908A196F1E92" } {
 
550
                                                #check if a conversation is open with that contact
 
551
                                                #no need to test either a chatwindow has been created or not, because MakeFor is going to do it ! 
 
552
                                                ::ChatWindow::MakeFor $chatid
 
553
                                                if { $eufguid == "4BD96FC0-AB17-4425-A14A-439185962DC8" } {
 
554
                                                        set producer 0
 
555
                                                } else {
 
556
                                                                set producer 1
 
557
                                                }
 
558
 
 
559
                                                status_log "we got an webcam invitation" red
 
560
 
 
561
                                                set context [base64::decode $context]
 
562
                                                set context [FromUnicode $context]
 
563
 
 
564
                                                #answerFtInvite $sid $chatid $branchuid $conntype
 
565
                                                # Let's send an ACK
 
566
                                                SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
567
 
 
568
                                                SessionList set $sid [list 0 0 0 $dest 0 $uid 0 "webcam" "" "$branchuid"]
 
569
                                                
 
570
                                                if { $context != "\{B8BE70DE-E2CA-4400-AE03-88FF85B9F4E8\}" } {
 
571
                                                        status_log "Received a video conferenced invitation.. we do not support this"
 
572
                                                        ::CAMGUI::InvitationRejected $chatid $sid $branchuid $uid
 
573
                                                        #::MSNCAM::RejectFT $chatid $sid $branchuid $uid
 
574
                                                        ::CAMGUI::GotVideoConferenceInvitation $chatid
 
575
                                                        return
 
576
                                                }
 
577
 
 
578
                                                
 
579
 
 
580
                                                ::CAMGUI::AcceptOrRefuse $chatid $dest $branchuid $cseq $uid $sid $producer
 
581
 
 
582
                                                status_log "MSNP2P | $sid $dest -> Sent ACK for INVITE\n" red
 
583
                                                return
 
584
                                        }
 
585
 
 
586
                                        # Let's send an ACK
 
587
                                        SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
588
                                        status_log "MSNP2P | $sid $dest -> Sent ACK for INVITE\n" red
 
589
 
 
590
                                        # Let's make and send a 200 OK Message
 
591
                                        set slpdata [MakeMSNSLP "OK" $dest [::config::getKey login] $branchuid [expr $cseq + 1] $uid 0 0 $sid]
 
592
                                        SendPacket [::MSN::SBFor $chatid] [MakePacket $sid $slpdata 1]
 
593
                                        status_log "MSNP2P | $sid $dest -> Sent 200 OK Message\n" red
 
594
                                        
 
595
                                        # Send Data Prep AFTER ACK received (set AfterAck)
 
596
                                        SessionList set $sid [list -1 -1 -1 -1 "DATAPREP" -1 -1 -1 -1 -1]
 
597
                                        
 
598
                                        return
 
599
                                }
 
600
                        } elseif { $ctype == "application/x-msnmsgr-transrespbody" } {
 
601
                                
 
602
                                set idx [expr [string first "Call-ID: \{" $data] + 10]
 
603
                                set idx2 [expr [string first "\}" $data $idx] -1]
 
604
                                set uid [string range $data $idx $idx2]
 
605
                                set sid [SessionList findcallid $uid]
 
606
                                set idx [expr [string first "Listening: " $data] + 11]
 
607
                                set idx2 [expr [string first "\r\n" $data $idx] -1]
 
608
                                set listening [string range $data $idx $idx2]
 
609
                                
 
610
                                #status_log "MSNP2P | $sid -> Got 200 OK for File transfer, parsing result\n"
 
611
                                #status_log "MSNP2P | $sid -> Found uid = $uid , lestening = $listening\n"
 
612
 
 
613
                                if { $sid != -1 }  {
 
614
                                        SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
615
                                        set type [lindex [SessionList get $sid] 7]
 
616
 
 
617
                                        if { $listening == "true" } {
 
618
                                                set idx [expr [string first "Nonce: \{" $data] + 8]
 
619
                                                set idx2 [expr [string first "\r\n" $data $idx] -2]
 
620
                                                set nonce [string range $data $idx $idx2]
 
621
 
 
622
                                                if {[string first "IPv4External-Addrs: " $data] != -1 } {
 
623
                                                        set idx [expr [string first "IPv4External-Addrs: " $data] + 20]
 
624
                                                        set idx2 [expr [string first "\r\n" $data $idx] -1]
 
625
                                                        set addr [string range $data $idx $idx2]
 
626
 
 
627
                                                        set idx [expr [string first "IPv4External-Port: " $data] + 19]
 
628
                                                        set idx2 [expr [string first "\r\n" $data $idx] -1]
 
629
                                                        set port [string range $data $idx $idx2]
 
630
                                                } else {
 
631
                                                        set idx [expr [string first "IPv4Internal-Addrs: " $data] + 20]
 
632
                                                        set idx2 [expr [string first "\r\n" $data $idx] -1]
 
633
                                                        set addr [string range $data $idx $idx2]
 
634
 
 
635
                                                        set idx [expr [string first "IPv4Internal-Port: " $data] + 19]
 
636
                                                        set idx2 [expr [string first "\r\n" $data $idx] -1]
 
637
                                                        set port [string range $data $idx $idx2]
 
638
                                                }
 
639
 
 
640
                                                status_log "MSNP2P | $sid -> Receiver is listening with $addr : $port\n" red
 
641
 
 
642
                                                #after 5500 "::MSNP2P::SendData $sid $chatid [lindex [SessionList get $sid] 8]"
 
643
                                                if {$type == "filetransfer" } {
 
644
                                                        ::MSN6FT::ConnectSockets $sid $nonce $addr $port 0
 
645
                                                } elseif { $type == "webcam" } {
 
646
                                                        ::MSNCAM::connectMsnCam2 $sid $nonce $addr $port 0
 
647
                                                }
 
648
                                        }
 
649
                                }
 
650
                        }
 
651
                }
 
652
                # Check if it is a 200 OK message
 
653
                if { [string first "MSNSLP/1.0 200 OK" $data] != -1 } {
 
654
                        # Send a 200 OK ACK
 
655
                        set first [string first "SessionID:" $data]
 
656
                        if { $first != -1 } {
 
657
                                set idx [expr [string first "SessionID:" $data] + 11]
 
658
                                set idx2 [expr [string first "\r\n" $data $idx] -1]
 
659
                                set sid [string range $data $idx $idx2]
 
660
                                set type [lindex [SessionList get $sid] 7]
 
661
 
 
662
                                if { $type == "ignore" } {
 
663
                                        #status_log "MSNP2P | $sid -> Ignoring packet! not for us!\n"
 
664
                                        return
 
665
                                }
 
666
 
 
667
                                #status_log "MSNP2P | $sid -> Got 200 OK message, sending an ACK for it\n" red
 
668
                                SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
669
                                if { $type == "filetransfer" } {
 
670
                                        ::MSN6FT::SendFTInvite $sid $chatid
 
671
                                }
 
672
                        } else {
 
673
                                set idx [expr [string first "Call-ID: \{" $data] + 10]
 
674
                                set idx2 [expr [string first "\}" $data $idx] -1]
 
675
                                set uid [string range $data $idx $idx2]
 
676
                                set sid [SessionList findcallid $uid]
 
677
                                set idx [expr [string first "Listening: " $data] + 11]
 
678
                                set idx2 [expr [string first "\r\n" $data $idx] -1]
 
679
                                set listening [string range $data $idx $idx2]
 
680
 
 
681
                                #status_log "MSNP2P | $sid -> Got 200 OK for File transfer, parsing result\n"
 
682
                                #status_log "MSNP2P | $sid -> Found uid = $uid , lestening = $listening\n"
 
683
 
 
684
 
 
685
                                set type [lindex [SessionList get $sid] 7]
 
686
 
 
687
                                if { $sid != -1 }  {
 
688
                                        SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
689
 
 
690
                                        if { $listening == "true" } {
 
691
                                                set idx [expr [string first "Nonce: \{" $data] + 8]
 
692
                                                set idx2 [expr [string first "\r\n" $data $idx] -2]
 
693
                                                set nonce [string range $data $idx $idx2]
 
694
 
 
695
                                                if {[string first "IPv4External-Addrs: " $data] != -1 } {
 
696
                                                        set idx [expr [string first "IPv4External-Addrs: " $data] + 20]
 
697
                                                        set idx2 [expr [string first "\r\n" $data $idx] -1]
 
698
                                                        set addr [string range $data $idx $idx2]
 
699
 
 
700
                                                        set idx [expr [string first "IPv4External-Port: " $data] + 19]
 
701
                                                        set idx2 [expr [string first "\r\n" $data $idx] -1]
 
702
                                                        set port [string range $data $idx $idx2]
 
703
                                                } else {
 
704
                                                        set idx [expr [string first "IPv4Internal-Addrs: " $data] + 20]
 
705
                                                        set idx2 [expr [string first "\r\n" $data $idx] -1]
 
706
                                                        set addr [string range $data $idx $idx2]
 
707
 
 
708
                                                        set idx [expr [string first "IPv4Internal-Port: " $data] + 19]
 
709
                                                        set idx2 [expr [string first "\r\n" $data $idx] -1]
 
710
                                                        set port [string range $data $idx $idx2]
 
711
                                                }
 
712
                                                status_log "MSNP2P | $sid -> Receiver is listening with $addr : $port\n" red
 
713
                                                #after 5500 "::MSNP2P::SendData $sid $chatid [lindex [SessionList get $sid] 8]"
 
714
                                                if { $type == "filetransfer" } {
 
715
                                                        ::MSN6FT::ConnectSockets $sid $nonce $addr $port 1
 
716
                                                } elseif { $type == "webcam" } {
 
717
                                                        setObjOption $sid accepted 1
 
718
                                                        ::MSNCAM::SendSyn $sid $chatid
 
719
                                                }
 
720
                                        } elseif { $listening == "false" } {
 
721
                                                status_log "MSNP2P | $sid -> Receiver is not listening, sending INVITE\n" red
 
722
                                                if { $type == "filetransfer" } {
 
723
                                                        ::MSN6FT::SendFTInvite2 $sid $chatid
 
724
                                                } elseif { $type == "webcam" } {
 
725
                                                        setObjOption $sid accepted 1
 
726
                                                        ::MSNCAM::SendSyn $sid $chatid
 
727
                                                        #::MSNCAM::SendAcceptInvite $sid $chatid
 
728
                                                }
 
729
                                        } else {
 
730
                                                status_log "Error sending file $filename, got answer to invite :\n$data\n\n" red
 
731
                                        }
 
732
                                }
 
733
                        }
 
734
 
 
735
 
 
736
                        return
 
737
 
 
738
 
 
739
                }
 
740
 
 
741
                # Check if we got BYE message
 
742
                if { [string first "BYE MSNMSGR:" $data] != -1 } {
 
743
                        # Lets get the call ID and find our SessionID
 
744
                        set idx [expr [string first "Call-ID: \{" $data] + 10]
 
745
                        set idx2 [expr [string first "\}" $data $idx] - 1]
 
746
                        set uid [string range $data $idx $idx2]
 
747
                        set sid [SessionList findcallid $uid]
 
748
                        status_log "MSNP2P | $sid -> Got BYE for UID : $uid\n" red
 
749
 
 
750
                        if { $sid != -1 } {
 
751
                                # Send a BYE ACK
 
752
                                SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
753
                                status_log "MSNP2P | $sid -> Sending BYE ACK\n" red
 
754
 
 
755
                                # If it's a file transfer, advise the user it has been canceled
 
756
                                if { [lindex [SessionList get $sid] 7] == "filetransfer" } {
 
757
                                        status_log "File transfer canceled\n"
 
758
                                        ::MSNP2P::SessionList set $sid [list -1 -1 -1 -1 -1 -1 -1 "ftcanceled" -1 -1]
 
759
                                        if { [::amsn::FTProgress ca $sid [lindex [SessionList get $sid] 6]] == -1 } {
 
760
                                                ::amsn::RejectFT $chatid "-2" $sid
 
761
                                        }
 
762
                                }
 
763
                                if { [lindex [SessionList get $sid] 7] == "webcam" } {
 
764
                                        status_log "Webcam canceled\n"
 
765
                                        ::MSNCAM::CamCanceled $chatid $sid
 
766
                                }
 
767
 
 
768
                                # Delete SessionID Data
 
769
                                SessionList unset $sid
 
770
 
 
771
                        } else {
 
772
                                status_log "MSNP2P | $sid -> Got a BYE for unexisting SessionID\n" red
 
773
                        }
 
774
                        return
 
775
                }
 
776
                # Check if we got DECLINE message
 
777
                if { [string first "603 Decline" $data] != -1 } {
 
778
                        # Lets get the call ID and find our SessionID
 
779
                        set idx [expr [string first "Call-ID: \{" $data] + 10]
 
780
                        set idx2 [expr [string first "\}" $data $idx] - 1]
 
781
                        set uid [string range $data $idx $idx2]
 
782
                        set sid [SessionList findcallid $uid]
 
783
                        status_log "MSNP2P | $sid -> Got DECLINE for UID : $uid\n" red
 
784
 
 
785
                        if { $sid != -1 } {
 
786
                                # Send a BYE ACK
 
787
                                SendPacket [::MSN::SBFor $chatid] [MakeACK $sid 0 $cTotalDataSize $cId $cAckId]
 
788
                                status_log "MSNP2P | $sid -> Sending DECLINE ACK\n" red
 
789
 
 
790
                                # If it's a file transfer, advise the user it has been canceled
 
791
                                if { [lindex [SessionList get $sid] 7] == "webcam" } {
 
792
                                        if { [getObjOption $sid accepted] != 1 } {
 
793
                                                ::CAMGUI::InvitationDeclined $chatid
 
794
                                        } else {
 
795
                                                ::MSNCAM::SendSyn $sid $chatid  
 
796
                                        }
 
797
                                }
 
798
 
 
799
 
 
800
                        } else {
 
801
                                status_log "MSNP2P | $sid -> Got a DECLINE for unexisting SessionID\n" red
 
802
                        }
 
803
                }
 
804
 
 
805
 
 
806
                # Let's check for data preparation messages and data messages
 
807
                if { $cSid != 0 } {
 
808
                        # Make sure this isn't a canceled FT
 
809
                        if { [lindex [SessionList get $cSid] 7] == "ftcanceled" } { return }
 
810
                        set sid $cSid
 
811
                        set fd [lindex [SessionList get $cSid] 6]
 
812
                        set type [lindex [SessionList get $cSid] 7]
 
813
 
 
814
                        #If it's a file transfer, display Progress bar
 
815
                        if { $type == "filetransfer" } {
 
816
                                ::amsn::FTProgress w $cSid "" [trans throughserver]
 
817
                                ::amsn::FTProgress r $cSid [lindex [SessionList get $cSid] 6] $cOffset $cTotalDataSize
 
818
                        }
 
819
                        if { $type != "webcam" && $fd != "" && $fd != 0 && $fd != -1 } {
 
820
                                # File already open and being written to (fd exists)
 
821
                                # Lets write data to file
 
822
                                puts -nonewline $fd [string range $data 0 [expr $cMsgSize - 1]]
 
823
                                #status_log "MSNP2P | $sid -> FD EXISTS, file already open... with fd = $fd --- $cOffset + $cMsgSize + $cTotalDataSize . Writing DATA to file\n" red
 
824
                                # Check if this is last part if splitted
 
825
                                if { [expr $cOffset + $cMsgSize] >= $cTotalDataSize } {
 
826
                                        close $fd
 
827
 
 
828
                                        set session_data [SessionList get $cSid]
 
829
                                        set user_login [lindex $session_data 3]
 
830
                                        set filename [lindex $session_data 8]
 
831
 
 
832
                                        # Lets send an ACK followed by a BYE if it's a buddy icon or emoticon
 
833
                                        #status_log "MSNP2P | $sid -> Sending an ACK for file received and sending a BYE\n" red
 
834
                                        SendPacket [::MSN::SBFor $chatid] [MakeACK $sid $cSid $cTotalDataSize $cId $cAckId]
 
835
 
 
836
                                        if { [lindex [SessionList get $cSid] 7] == "bicon" } {
 
837
                                                SendPacket [::MSN::SBFor $chatid] [MakePacket $sid [MakeMSNSLP "BYE" $user_login [::config::getKey login] "19A50529-4196-4DE9-A561-D68B0BF1E83F" 0 [lindex $session_data 5] 0 0] 1]
 
838
 
 
839
                                                #set filename2 [::MSNP2P::GetFilenameFromMSNOBJ [::abook::getVolatileData $user_login msnobj]]
 
840
                                                set filename2 [::abook::getContactData $user_login displaypicfile ""]
 
841
                                                status_log "MSNP2P | $sid -> Got picture with file : $filename and $filename2\n" blue
 
842
                                                if {$filename == $filename2 } {
 
843
 
 
844
                                                        status_log "MSNP2P | $sid -> Closed file $filename.. finished writing\n" red
 
845
                                                        #set file [png_to_gif [file join $HOME displaypic cache ${filename}.png]]
 
846
                                                        set file [file join $HOME displaypic cache ${filename}.png]
 
847
                                                        if { $file != "" } {
 
848
                                                                
 
849
                                                                if {[catch {image create photo user_pic_${user_login} -file [file join $HOME displaypic cache "${filename}.png"] -format cximage}] } {
 
850
                                                                        image create photo user_pic_${user_login} -file [::skin::GetSkinFile displaypic nopic.gif] -format cximage
 
851
                                                                }
 
852
 
 
853
                                                                set desc_file "[file join $HOME displaypic cache ${filename}.dat]"
 
854
                                                                create_dir [file join $HOME displaypic]
 
855
                                                                set fd [open [file join $HOME displaypic $desc_file] w]
 
856
                                                                status_log "Writing description to $desc_file\n"
 
857
                                                                puts $fd "[clock format [clock seconds] -format %x]\n$user_login"
 
858
                                                                close $fd
 
859
 
 
860
                                                        }
 
861
                                                } else {
 
862
                                                        #set file [png_to_gif [file join $HOME smileys cache ${filename}.png]]
 
863
                                                        set file [file join $HOME smileys cache ${filename}.png]
 
864
                                                        if { $file != "" } {
 
865
                                                                set tw [::ChatWindow::GetOutText [::ChatWindow::For $chatid]]
 
866
                                                                #set file [filenoext $file].gif
 
867
                                                                set scrolling [::ChatWindow::getScrolling $tw]
 
868
                                                                catch {image create photo custom_smiley_${filename} -file "[file join $HOME smileys cache ${filename}.png]" -format cximage}
 
869
                                                                if { $scrolling } { ::ChatWindow::Scroll $tw }
 
870
                                                        }
 
871
                                                }
 
872
 
 
873
                                        } elseif { [lindex [SessionList get $cSid] 7] == "filetransfer" } {
 
874
                                                # Display message that file transfer is finished...
 
875
                                                status_log "MSNP2P | $cSid -> File transfer finished!\n"
 
876
                                                ::amsn::FTProgress fr $cSid [lindex [SessionList get $cSid] 6] $cOffset $cTotalDataSize
 
877
                                                SessionList set $cSid [list -1 -1 -1 -1 -1 -1 -1 "filetransfersuccessfull" -1 -1]
 
878
                                        }
 
879
                                }
 
880
                        } elseif { $cMsgSize == 4 } {
 
881
                                # We got ourselves a DATA PREPARATION message, lets open file and send ACK
 
882
                                set session_data [SessionList get $sid]
 
883
                                set user_login [lindex $session_data 3]
 
884
                                #status_log "MSNP2P | $sid $user_login -> Got data preparation message, opening file for writing\n" red
 
885
                                set filename [lindex $session_data 8]
 
886
                                #set filename2 [::MSNP2P::GetFilenameFromMSNOBJ [::abook::getVolatileData $user_login msnobj]]
 
887
                                set filename2 [::abook::getContactData $user_login displaypicfile ""]
 
888
                                #status_log "MSNP2P | $sid $user_login -> opening file $filename for writing with $filename2 as user msnobj\n\n" blue
 
889
                                if { $filename == $filename2 } {
 
890
                                        create_dir [file join $HOME displaypic cache]
 
891
                                        set fd [open "[file join $HOME displaypic cache ${filename}.png]" w]
 
892
                                } else {
 
893
                                        create_dir [file join $HOME smileys cache]
 
894
                                        set fd [open "[file join $HOME smileys cache ${filename}.png]" w]
 
895
                                }
 
896
 
 
897
                                fconfigure $fd -translation {binary binary}
 
898
                                SendPacket [::MSN::SBFor $chatid] [MakeACK $sid $cSid $cTotalDataSize $cId $cAckId]
 
899
                                #status_log "MSNP2P | $sid $user_login -> Sent an ACK for DATA PREP Message\n" red
 
900
                                SessionList set $sid [list -1 -1 -1 -1 -1 -1 $fd -1 -1 -1]
 
901
                        } elseif { $type == "webcam" } {
 
902
                                # WEBCAM TO COMPLETE
 
903
 
 
904
                                set h1 [string range $data 0 3]
 
905
                                set h2 [string range $data 4 9]
 
906
                                set msg [string range $data 10 [expr { $cMsgSize - 1}]]
 
907
 
 
908
                                set msg [FromUnicode $msg]
 
909
 
 
910
                                status_log "Received data for webcam $sid : $data\n$msg\n" red
 
911
 
 
912
                                if {[expr $cOffset + $cMsgSize] >= $cTotalDataSize} {
 
913
                                        SendPacket [::MSN::SBFor $chatid] [MakeACK $sid $cSid $cTotalDataSize $cId $cAckId]
 
914
                                }
 
915
 
 
916
                                if { $msg == "syn\x00" } {
 
917
 
 
918
                                        ::MSNCAM::SendSyn $sid $chatid
 
919
 
 
920
                                        ::MSNCAM::SendAck $sid $chatid
 
921
 
 
922
                                } elseif { $msg == "ack\x00" } {
 
923
                                        set producer [getObjOption $sid producer]
 
924
                                        status_log "Received the ack for webcam\n" red
 
925
 
 
926
                                        if {$producer} {
 
927
                                                status_log "We should send the XML\n" red
 
928
                                                ::MSNCAM::SendXML $chatid $sid
 
929
                                        }
 
930
 
 
931
                                } elseif { $msg == "receivedViewerData\x00" } {
 
932
                                        status_log "ReceivedViewData received\n" red
 
933
                                        ::MSNCAM::ConnectSockets $sid
 
934
                                } elseif {[string first "<producer>" $msg] == 0 || [string first "<viewer>" $msg] == 0 || $cOffset != 0} {
 
935
                                        set xml [getObjOption $sid xml]
 
936
                                        set xml "${xml}[string range $data 0 [expr { $cMsgSize - 1}]]"
 
937
 
 
938
                                        setObjOption $sid xml $xml
 
939
 
 
940
                                        if { [expr $cOffset + $cMsgSize] >= $cTotalDataSize } {
 
941
                                                set xml [string range $xml 10 end]
 
942
                                                setObjOption $sid xml $xml
 
943
 
 
944
                                                ::MSNCAM::ReceivedXML $chatid $sid
 
945
                                        }
 
946
 
 
947
                                } elseif { [string first "ReflData:" $msg] == 0 } {
 
948
                                        set refldata [string range $msg 9 end-1]
 
949
                                        set refldata [binary format H* $refldata]
 
950
 
 
951
                                        ::MSNCAM::ConnectToReflector $sid $refldata
 
952
 
 
953
                                } else {
 
954
                                        status_log "UNKNOWN" red
 
955
                                }
 
956
 
 
957
 
 
958
                        } elseif {$sid == 64} {
 
959
                                set msg [FromUnicode $data]
 
960
                                set ink_message [getObjOption $sid ink_message_$cId]
 
961
                                set ink_message "${ink_message}[string range $data 0 [expr { $cMsgSize - 1}]]"
 
962
                                setObjOption $sid ink_message_$cId $ink_message
 
963
 
 
964
                                if {[expr $cOffset + $cMsgSize] >= $cTotalDataSize} {
 
965
                                        setObjOption $sid ink_message_$cId ""
 
966
                                        SendPacket [::MSN::SBFor $chatid] [MakeACK $sid $cSid $cTotalDataSize $cId $cAckId]
 
967
                                        set ink_message [FromUnicode $ink_message]
 
968
                                        set idx [string first "\r\n\r\n" $ink_message]
 
969
                                        incr idx 4
 
970
                                        if {[string first "\x00" $ink_message $idx] == $idx } {
 
971
                                                incr idx
 
972
                                        }
 
973
                                        set body [string range $ink_message $idx end]
 
974
                                
 
975
                                        if { [string first "base64:" $body] != -1 } {
 
976
                                                set data [::base64::decode [string range $body 7 end]]
 
977
                                        } else {
 
978
                                                set data $body
 
979
                                        }
 
980
                                        set img [image create photo -data $data]
 
981
                                        set user [lindex [::MSN::usersInChat $chatid] 0]
 
982
                                        set nick [::abook::getDisplayNick $user]
 
983
                                        set p4c_enabled 0
 
984
                                        status_log "got ink from $user - $nick with image $img"
 
985
                                        SendMessageFIFO [list ::amsn::ShowInk $chatid $user $nick $img ink $p4c_enabled] "::amsn::messages_stack($chatid)" "::amsn::messages_flushing($chatid)"
 
986
                                }
 
987
 
 
988
                        } else {
 
989
                                status_log "Received data for unknown type : $sid\n" red
 
990
                        }
 
991
                }
 
992
        }
 
993
 
 
994
        #//////////////////////////////////////////////////////////////////////////////
 
995
        # RequestObject ( chatid msnobject filename)
 
996
        # This function creates the invitation packet in order to receive an MSNObject (custom emoticon and display buddy for now)
 
997
        # chatid : Chatid from which we will request the object
 
998
        # dest : The email of the user that will receive our request
 
999
        # msnobject : The object we want to request (has to be url decoded)
 
1000
        # filename: the file where data should be saved to
 
1001
        proc RequestObject { chatid dest msnobject} {
 
1002
                # Let's create a new session
 
1003
                set sid [expr int([expr rand() * 1000000000])%125000000 + 4]
 
1004
                # Generate BranchID and CallID
 
1005
                set branchid "[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]"
 
1006
                set callid "[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]]-[format %X [myRand 4369 65450]][format %X [myRand 4369 65450]][format %X [myRand 4369 65450]]"
 
1007
 
 
1008
                SessionList set $sid [list 0 0 0 $dest 0 $callid 0 "bicon" [::MSNP2P::GetFilenameFromMSNOBJ $msnobject] ""]
 
1009
 
 
1010
                # Create and send our packet
 
1011
                set slpdata [MakeMSNSLP "INVITE" $dest [::config::getKey login] $branchid 0 $callid 0 0 "A4268EEC-FEC5-49E5-95C3-F126696BDBF6" $sid 1 [string map { "\n" "" } [::base64::encode "$msnobject\x00"]]]
 
1012
                SendPacket [::MSN::SBFor $chatid] [MakePacket $sid $slpdata 1]
 
1013
                status_log "Sent an INVITE to $dest on chatid $chatid of object $msnobject\n" red
 
1014
        }
 
1015
 
 
1016
 
 
1017
        #//////////////////////////////////////////////////////////////////////////////
 
1018
        # MakePacket ( sid slpdata [nullsid] [MsgId] [TotalSize] [Offset] [Destination] )
 
1019
        # This function creates the appropriate MSNP2P packet with the given SLP info
 
1020
        # This will be used for everything except for ACK's
 
1021
        # slpdata       : the SLP info created by MakeMSNSLP that will be included in the packet
 
1022
        #                 it could also be binary data that will be sent in the P2P packet
 
1023
        # sid           : the session id
 
1024
        # nullsid       : 0 to add sid to header, 1 to put 0 instead of sid in header (usefull for negot + bye)
 
1025
        # Returns the MSNP2P packet (half text half binary)
 
1026
        proc MakePacket { sid slpdata {nullsid "0"} {MsgId "0"} {TotalSize "0"} {Offset "0"} {Destination "0"} {AfterAck "0"} {flags "0"}} {
 
1027
 
 
1028
                # Let's get our session id variables and put them in a list
 
1029
                # If sessionid is 0, means we want to initiate a new session
 
1030
                if { $sid != 0 } {
 
1031
                        set SessionInfo [SessionList get $sid]
 
1032
                        set MsgId [lindex $SessionInfo 0]
 
1033
                        set TotalSize [lindex $SessionInfo 1]
 
1034
                        set Offset [lindex $SessionInfo 2]
 
1035
                        set Destination [lindex $SessionInfo 3]
 
1036
                }
 
1037
 
 
1038
                # Here is our text header
 
1039
                set theader "MIME-Version: 1.0\r\nContent-Type: application/x-msnmsgrp2p\r\nP2P-Dest: $Destination\r\n\r\n"
 
1040
 
 
1041
                # We start by creating the 48 byte binary header
 
1042
                if { $nullsid != 0 } {
 
1043
                        # session id field set to 0 during negotiation and bye
 
1044
                        set bheader [binary format i 0]
 
1045
                } else {
 
1046
                        # normal message
 
1047
                        set bheader [binary format i $sid]
 
1048
                }
 
1049
 
 
1050
                if { $MsgId == 0 } {
 
1051
                        # No MsgId let's generate one and add to our list
 
1052
                        set MsgId [expr int([expr rand() * 1000000]) + 4]
 
1053
                } elseif { $Offset == 0 } {
 
1054
                        # Offset is different than 0, we need to incr the MsgId to prepare our next message
 
1055
                        incr MsgId
 
1056
                }
 
1057
 
 
1058
                if {[string is digit $Offset] == 0 || $Offset == ""} {
 
1059
                        set Offset 0
 
1060
                }
 
1061
 
 
1062
                append bheader [binary format i $MsgId]
 
1063
                append bheader [binword $Offset]
 
1064
 
 
1065
                set CurrentSize [string length $slpdata]
 
1066
                # We must set TotalSize to the size of data if it is > 1202 bytes otherwise we set to 0
 
1067
                if { $TotalSize == 0 } {
 
1068
                        # This isn't a split message
 
1069
                        append bheader "[binword $CurrentSize][binary format i $CurrentSize]"
 
1070
                } else {
 
1071
                        # This is a split message
 
1072
                        append bheader "[binword $TotalSize][binary format i $CurrentSize]"
 
1073
                        incr Offset $CurrentSize
 
1074
                        if { $Offset >= $TotalSize } {
 
1075
                                # We have finished sending the last part of the message
 
1076
                                set Offset 0
 
1077
                                set TotalSize 0
 
1078
                        }
 
1079
                }
 
1080
 
 
1081
                # Set flags to 0
 
1082
                append bheader [binary format i $flags]
 
1083
 
 
1084
                # Just give the Ack Session ID some dumbo random number
 
1085
                append bheader [binary format i [myRand 4369 6545000]]
 
1086
                #append bheader [binary format i 67152542]
 
1087
 
 
1088
                # Set last 2 ack fields to 0
 
1089
                append bheader [binary format i 0][binword 0]
 
1090
 
 
1091
                # Now the footer
 
1092
                if { $nullsid == 1 } {
 
1093
                        # Negotiating Session so set to 0
 
1094
                        set bfooter [binary format I 0]
 
1095
                } else {
 
1096
                        # Either sending a display pic, or an emoticon so set to 1
 
1097
                        set bfooter [binary format I 1]
 
1098
                }
 
1099
 
 
1100
                # Combine it all
 
1101
                set packet "${theader}${bheader}${slpdata}${bfooter}"
 
1102
                #status_log "Sent a packet with header $theader\n" red
 
1103
 
 
1104
                unset bheader
 
1105
                unset bfooter
 
1106
                unset slpdata
 
1107
 
 
1108
                # Save new Session Variables into SessionList
 
1109
                SessionList set $sid [list $MsgId $TotalSize $Offset -1 -1 -1 -1 -1 -1 -1]
 
1110
 
 
1111
                return $packet
 
1112
        }
 
1113
 
 
1114
 
 
1115
        #//////////////////////////////////////////////////////////////////////////////
 
1116
        # MakeACK (sid originalsid originalsize originalid originaluid)
 
1117
        # This function creates an ack packet for msnp2p
 
1118
        # original* arguments are all arguments of the message we want to ack
 
1119
        # sid has to be != 0
 
1120
        # Returns the ACK packet
 
1121
        proc MakeACK { sid originalsid originalsize originalid originaluid } {
 
1122
                set new 0
 
1123
                if { $sid != 0 } {
 
1124
                        set SessionInfo [SessionList get $sid]
 
1125
                        set MsgId [lindex $SessionInfo 0]
 
1126
                        set Destination [lindex $SessionInfo 3]
 
1127
                } else {
 
1128
                        return
 
1129
                }
 
1130
 
 
1131
                if { $MsgId == 0 } {
 
1132
                        # No MsgId let's generate one and add to our list
 
1133
                        set MsgId [expr int([expr rand() * 1000000]) + 10]
 
1134
                        set new 1
 
1135
                } else {
 
1136
                        incr MsgId
 
1137
                }
 
1138
 
 
1139
                # The text header
 
1140
                set theader "MIME-Version: 1.0\r\nContent-Type: application/x-msnmsgrp2p\r\nP2P-Dest: $Destination\r\n\r\n"
 
1141
 
 
1142
                # Set the binary header and footer
 
1143
                set b [binary format ii $originalsid $MsgId][binword 0][binword $originalsize][binary format iiii 0 2 $originalid $originaluid][binword $originalsize][binary format I 0]
 
1144
 
 
1145
                # Save new Session Variables into SessionList
 
1146
                if { $new == 1 } {
 
1147
                        incr MsgId -4
 
1148
                }
 
1149
                SessionList set $sid [list $MsgId -1 -1 -1 -1 -1 -1 -1 -1 -1]
 
1150
 
 
1151
                return "${theader}${b}"
 
1152
        }
 
1153
 
 
1154
 
 
1155
        #//////////////////////////////////////////////////////////////////////////////
 
1156
        #       # MakeMSNSLP ( method to from branchuid cseq maxfwds contenttentype [A] [B] [C] [D] [E] [F] [G])
 
1157
        # This function creates the appropriate MSNSLP packets
 
1158
        # method :              INVITE, BYE, OK, DECLINE
 
1159
        # contenttype :         0 for application/x-msnmsgr-sessionreqbody (Starting a session) or sessionclosebody for a BYE
 
1160
        #                       1 for application/x-msnmsgr-transreqbody (Starting transfer) or sessionclosebody for a BYE and use A
 
1161
        #                                                                                                                 as context
 
1162
        #                       2 for application/x-msnmsgr-transrespbody (Starting transfer)
 
1163
        #                       3 for null (starting webcam)
 
1164
        #
 
1165
        #
 
1166
        # If INVITE method is chosen then A, B, C, D and/or E are used dependinf on contenttype
 
1167
        # for 0 we got : "EUF-GUID", "SessionID", "AppID" and "Context" (E not used)
 
1168
        # for 1 we got : "Bridges", "NetID", "Conn-Type", "UPnPNat" and "ICF"
 
1169
        # for 2 we got : "Bridge", "Listening", "Nonce", "IPv4External-Addrs","IPv4External-Port"
 
1170
        #                "IPv4Internal-Addrs" and "IPv4Internal-Port"
 
1171
        #
 
1172
        # If OK method is chosen then A to G are used depending on contenttype
 
1173
        # for 0 we got : "SessionID"
 
1174
        # for 1 we got : "Bridge", "Listening", "Nonce", "IPv4External-Addrs","IPv4External-Port"
 
1175
        #                "IPv4Internal-Addrs" and "IPv4Internal-Port"
 
1176
        # Returns the formated MSNSLP data
 
1177
        proc MakeMSNSLP { method to from branchuid cseq uid maxfwds contenttype {A ""} {B ""} {C ""} {D ""} {E ""} {F ""} {G ""} } {
 
1178
 
 
1179
                # Generate start line
 
1180
                if { $method == "INVITE" } {
 
1181
                        set data "INVITE MSNMSGR:${to} MSNSLP/1.0\r\n"
 
1182
                } elseif { $method == "BYE" } {
 
1183
                        set data "BYE MSNMSGR:${to} MSNSLP/1.0\r\n"
 
1184
                } elseif { $method == "OK" } {
 
1185
                        set data "MSNSLP/1.0 200 OK\r\n"
 
1186
                } elseif { $method == "DECLINE" } {
 
1187
                        set data "MSNSLP/1.0 603 DECLINE\r\n"
 
1188
                }
 
1189
 
 
1190
                # Lets create our message body first (so we can calc it's length for the header)
 
1191
                set body ""
 
1192
                if { $method == "INVITE" } {
 
1193
                        if { $contenttype == 0 } {
 
1194
                                append body "EUF-GUID: {${A}}\r\nSessionID: ${B}\r\nAppID: ${C}\r\nContext: ${D}\r\n"
 
1195
                        } elseif { $contenttype == 1 } {
 
1196
                                append body "Bridges: ${A}\r\nNetID: ${B}\r\nConn-Type: ${C}\r\nUPnPNat: ${D}\r\nICF: ${E}\r\n"
 
1197
                        } else {
 
1198
                                append body "Bridge: ${A}\r\nListening: ${B}\r\nNonce: \{${C}\}\r\n"
 
1199
                                if {${B} == "true" } {
 
1200
                                        if { [::abook::getDemographicField conntype] == "IP-Restrict-NAT" } {
 
1201
                                                append body "IPv4External-Addrs: ${D}\r\nIPv4External-Port: ${E}\r\nIPv4Internal-Addrs: ${F}\r\nIPv4Internal-Port: ${G}\r\n"
 
1202
                                        } else {
 
1203
                                                append body "IPv4Internal-Addrs: ${D}\r\nIPv4Internal-Port: ${E}\r\n"
 
1204
                                        }
 
1205
                                }
 
1206
 
 
1207
                        }
 
1208
                } elseif { $method == "OK" } {
 
1209
                        if { $contenttype == 0 } {
 
1210
                                append body "SessionID: ${A}\r\n"
 
1211
                        } else {
 
1212
                                append body "Bridge: ${A}\r\nListening: ${B}\r\nNonce: \{${C}\}\r\n"
 
1213
                                if {${B} == "true" } {
 
1214
                                        if { [::abook::getDemographicField conntype] == "IP-Restrict-NAT" } {
 
1215
                                                append body "IPv4External-Addrs: ${D}\r\nIPv4External-Port: ${E}\r\nIPv4Internal-Addrs: ${F}\r\nIPv4Internal-Port: ${G}\r\n"
 
1216
                                        } else {
 
1217
                                                append body "IPv4Internal-Addrs: ${D}\r\nIPv4Internal-Port: ${E}\r\n"
 
1218
                                        }
 
1219
                                }
 
1220
 
 
1221
                        }
 
1222
                } elseif { $method == "DECLINE" } {
 
1223
                        append body "SessionID: ${A}\r\n"
 
1224
                } elseif { $method == "BYE" && $contenttype == 1} {
 
1225
                        append body "Context: ${A}"
 
1226
 
 
1227
                }
 
1228
                append body "\r\n\x00"
 
1229
 
 
1230
                # Here comes the message header
 
1231
                append data "To: <msnmsgr:${to}>\r\nFrom: <msnmsgr:${from}>\r\nVia: MSNSLP/1.0/TLP ;branch={${branchuid}}\r\nCSeq: ${cseq}\r\nCall-ID: {${uid}}\r\nMax-Forwards: ${maxfwds}\r\n"
 
1232
                if { $method == "BYE" } {
 
1233
                        append data "Content-Type: application/x-msnmsgr-sessionclosebody\r\n"
 
1234
                } else {
 
1235
                        if { $contenttype == 0 } {
 
1236
                                append data "Content-Type: application/x-msnmsgr-sessionreqbody\r\n"
 
1237
                        } elseif { $contenttype == 1 } {
 
1238
                                append data "Content-Type: application/x-msnmsgr-transreqbody\r\n"
 
1239
                        } elseif { $contenttype == 2 } {
 
1240
                                append data "Content-Type: application/x-msnmsgr-transrespbody\r\n"
 
1241
                        } elseif { $contenttype == 3 } {
 
1242
                                append data "Content-Type: null\r\n"
 
1243
                                set body ""
 
1244
                        }
 
1245
                }
 
1246
                append data "Content-Length: [expr [string length $body]]\r\n\r\n"
 
1247
 
 
1248
                append data $body
 
1249
                unset body
 
1250
 
 
1251
                #status_log $data
 
1252
                return $data
 
1253
        }
 
1254
 
 
1255
        #//////////////////////////////////////////////////////////////////////////////
 
1256
        # SendData ( sid chatid )
 
1257
        # This procedure sends the data given by the filename in the Session vars given by SessionID
 
1258
        proc SendData { sid chatid filename } {
 
1259
 
 
1260
 
 
1261
                SessionList set $sid [list -1 [file size "${filename}"] -1 -1 -1 -1 -1 -1 -1 -1]
 
1262
                set fd [lindex [SessionList get $sid] 6]
 
1263
                if { $fd == 0 } {
 
1264
                        set fd [open "${filename}"]
 
1265
                        SessionList set $sid [list -1 -1 -1 -1 -1 -1 $fd -1 -1 -1]
 
1266
                        fconfigure $fd -translation binary
 
1267
                }
 
1268
                if { $fd == "" } {
 
1269
                        #                       set sock [sb get [MSN::SBFor $chatid] sock]
 
1270
 
 
1271
                        #                       if { $sock != "" } {
 
1272
                        #                               fileevent $sock writable ""
 
1273
                        #                       }
 
1274
                        return
 
1275
                }
 
1276
                set chunk [read $fd 1200]
 
1277
                SendPacket [::MSN::SBFor $chatid] [MakePacket $sid $chunk 0 0 0 0 0 0 32]
 
1278
                unset chunk
 
1279
 
 
1280
                #status_log "[SessionList get $sid]\n"
 
1281
                if { [lindex [SessionList get $sid] 1] == 0 } {
 
1282
                        # All file has been sent
 
1283
                        close $fd
 
1284
                        unset fd
 
1285
                        # We finished sending the data, set appropriate Afterack and Fd
 
1286
                        SessionList set $sid [list -1 -1 -1 -1 DATASENT -1 0 -1 -1]
 
1287
                } else {
 
1288
                        #       set sock [sb get [MSN::SBFor $chatid] sock]
 
1289
                        # Still need to send
 
1290
                        #                       if { $sock != "" } {
 
1291
                        after 100 "[list ::MSNP2P::SendData $sid $chatid ${filename}]"
 
1292
                        # }
 
1293
                }
 
1294
 
 
1295
 
 
1296
        }
 
1297
 
 
1298
 
 
1299
        proc SendDataFile { sid chatid filename match } {
 
1300
 
 
1301
 
 
1302
 
 
1303
                if { [lindex [::MSNP2P::SessionList get $sid] 4] != "$match"} {
 
1304
                        return
 
1305
                }
 
1306
 
 
1307
                status_log "state is [lindex [::MSNP2P::SessionList get $sid] 4] => sending through SB\n\n" red;
 
1308
 
 
1309
                #return
 
1310
 
 
1311
                SessionList set $sid [list -1 [file size "${filename}"] -1 -1 -1 -1 -1 -1 -1 -1]
 
1312
                set fd [lindex [SessionList get $sid] 6]
 
1313
                if { $fd == 0 || $fd == "" } {
 
1314
                        set fd [open "${filename}"]
 
1315
                        SessionList set $sid [list -1 -1 -1 -1 -1 -1 $fd -1 -1 -1]
 
1316
                        fconfigure $fd -translation {binary binary}
 
1317
                }
 
1318
                if { $fd == "" } {
 
1319
                        return
 
1320
                }
 
1321
                ::amsn::FTProgress w $sid "" [trans throughserver]
 
1322
 
 
1323
                #               SendPacketExt [::MSN::SBFor $chatid] $sid [read $fd] 0 0 0 0 0 0 16777264
 
1324
                #               close $fd
 
1325
 
 
1326
 
 
1327
                set sbn [::MSN::SBFor $chatid]
 
1328
                set sock [$sbn cget -sock]
 
1329
 
 
1330
                set offset 0
 
1331
                SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1]
 
1332
 
 
1333
                if { [fileevent $sock writable] == "" } {
 
1334
                        status_log "assining new fileevent proc\n"
 
1335
                        fileevent $sock writable "::MSNP2P::SendDataEvent $sbn $sid $fd"
 
1336
                }
 
1337
 
 
1338
 
 
1339
 
 
1340
        }
 
1341
 
 
1342
        proc SendDataEvent { sbn sid fd } {
 
1343
 
 
1344
 
 
1345
                set sock [$sbn cget -sock]
 
1346
                fileevent $sock writable ""
 
1347
                #return
 
1348
 
 
1349
                set offset [lindex [SessionList get $sid] 2]
 
1350
                set filesize [lindex [SessionList get $sid] 1]
 
1351
 
 
1352
                if { $offset == "" } {
 
1353
                        close $fd
 
1354
                        return
 
1355
                }
 
1356
 
 
1357
                if { [lindex [::MSNP2P::SessionList get $sid] 7] == "ftcanceled" } {
 
1358
                        close $fd
 
1359
                        return
 
1360
                }
 
1361
 
 
1362
                set data [read $fd 1202]
 
1363
                #               status_log "Reading 1202 bytes of data : got [string length $data]"
 
1364
                if { [string length $data] >= 1202 } {
 
1365
                        set msg [MakePacket $sid $data 0 0 0 0 0 0 16777264]
 
1366
                        set msg_len [string length $msg]
 
1367
                        puts -nonewline $sock "MSG [incr ::MSN::trid] D $msg_len\r\n$msg"
 
1368
                        set offset [expr $offset + 1202]
 
1369
                        SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1]
 
1370
                        ::amsn::FTProgress s $sid "" $offset $filesize
 
1371
                        catch {after 200 [list fileevent $sock writable "::MSNP2P::SendDataEvent $sbn $sid $fd"]}
 
1372
                } else {
 
1373
 
 
1374
                        set msg [MakePacket $sid $data 0 0 0 0 0 0 16777264]
 
1375
                        set msg_len [string length $msg]
 
1376
                        puts -nonewline $sock "MSG [incr ::MSN::trid] D $msg_len\r\n$msg"
 
1377
                        set offset [expr $offset + 1202]
 
1378
                        SessionList set $sid [list -1 -1 0 -1 -1 -1 -1 -1 -1 -1 ]
 
1379
 
 
1380
                        set msgId [expr [lindex [SessionList get $sid] 0] + 1]
 
1381
                        SessionList set $sid [list $msgId -1 0 -1 DATASENT -1 0 -1 -1 -1]
 
1382
                        close $fd
 
1383
                        unset fd
 
1384
 
 
1385
                        ::amsn::FTProgress fs $sid ""
 
1386
                }
 
1387
        }
 
1388
 
 
1389
 
 
1390
 
 
1391
        #//////////////////////////////////////////////////////////////////////////////
 
1392
        # SendPacket ( sbn msg )
 
1393
        # This function sends the packet given by (msg) into the given (sbn)
 
1394
        proc SendPacket { sbn msg } {
 
1395
                #       if { [string length $msg] > 1202 }
 
1396
                set msg_len [string length $msg]
 
1397
                ::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg"
 
1398
        }
 
1399
 
 
1400
        proc SendPacketExt { sbn sid slpdata {nullsid "0"} {MsgId "0"} {TotalSize "0"} {Offset "0"} {Destination "0"} {AfterAck "0"} {flags "0"}} {
 
1401
                set offset 0
 
1402
                SessionList set $sid [list -1 [string length $slpdata] $offset -1 -1 -1 -1 -1 -1 -1]
 
1403
                set fd [$sbn cget -sock]
 
1404
                status_log "Got socket $fd\n"
 
1405
                if { [fileevent $fd writable] == "" } {
 
1406
                        status_log "assining new fileevent proc\n"
 
1407
                        fileevent $fd writable "::MSNP2P::SendPacketExtEvent $sbn $sid [list $slpdata] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags"
 
1408
                }
 
1409
        }
 
1410
 
 
1411
        proc SendPacketExtEvent { sbn sid slpdata {nullsid "0"} {MsgId "0"} {TotalSize "0"} {Offset "0"} {Destination "0"} {AfterAck "0"} {flags "0"} } {
 
1412
                set fd [$sbn cget -sock]
 
1413
                fileevent $fd writable ""
 
1414
 
 
1415
                #status_log "got sbn : $sbn, $fd\nsid : $sid\nslpdata: $slpdata \n$nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags\n\n"  red
 
1416
 
 
1417
                set offset [lindex [SessionList get $sid] 2]
 
1418
 
 
1419
                if { $offset == "" } {
 
1420
                        return
 
1421
                }
 
1422
 
 
1423
                if { [expr $offset + 1202] < [string length $slpdata] } {
 
1424
                        set msg [MakePacket $sid [string range $slpdata $offset [expr $offset + 1201]] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags]
 
1425
                        set msg_len [string length $msg]
 
1426
                        ::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg"
 
1427
                        set offset [expr $offset + 1202]
 
1428
                        SessionList set $sid [list -1 -1 $offset -1 -1 -1 -1 -1 -1 -1]
 
1429
                        after 200 [list fileevent $fd writable "::MSNP2P::SendPacketExtEvent $sbn $sid [list $slpdata] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags" ]
 
1430
                } else {
 
1431
 
 
1432
                        set msg [MakePacket $sid [string range $slpdata $offset [expr $offset + 1201]] $nullsid $MsgId $TotalSize $Offset $Destination $AfterAck $flags]
 
1433
                        set msg_len [string length $msg]
 
1434
                        ::MSN::WriteSBNoNL $sbn "MSG" "D $msg_len\r\n$msg"
 
1435
                        set offset [expr $offset + 1202]
 
1436
                        SessionList set $sid [list -1 -1 0 -1 -1 -1 -1 -1 -1 -1 ]
 
1437
                }
 
1438
        }
 
1439
 
 
1440
}