This file is indexed.

/usr/share/amsn/remote.tcl is in amsn-data 0.98.9-1ubuntu3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
#########################################################
### remote.tcl v 1.0	2003/05/22   KaKaRoTo
#########################################################

::Version::setSubversionId {$Id: remote.tcl 9886 2008-05-15 01:06:32Z kakaroto $}

if { $initialize_amsn == 1 } {
	global remote_port remote_auth remote_sock_lock remote_sock
   
	set remote_port 0
	set remote_auth 0
	set remote_sock_lock 0
	set remote_sock 0
	set remote_authtimer 0
}

proc remote_check_online { } {
	if { [::MSN::myStatusIs] != "FLN" } {
		write_remote "[trans connected]..."
		return
	} else {
		after 1000 "remote_check_online"
	}
}

proc remote_touchauthtimer {} {
	global remote_authtimer
	set remote_authtimer 0
}

namespace eval ::remote {

	# connect 
	# connects you to your account
	#
	proc connect { } {
	
		if { [catch { ::MSN::connect } res] } {
			write_remote "[trans connecterror]"
		} else {
			write_remote "[trans connecting] ..." 
			after 1000 "remote_check_online"
		}
	}

	# logout
	# logs you out from the current session
	#
	proc logout { } {
		write_remote "[trans logout]"
		preLogout "::MSN::logout" 1
	}

	# help
	# prints the help message from the remote.help file
	#
	proc help { } {

		set fd [open "remote.help" r]
		set printhelp [read $fd]
		close $fd

		write_remote "$printhelp"
  
	}

	# online
	# Shows list of users connected
	#
	proc online { } {
		foreach username [::MSN::getList FL] {
			set state_code [::abook::getVolatileData $username state]

			if { $state_code !="FLN" } {
				write_remote "$username - [::abook::getNick $username] --- [trans status] : [trans [::MSN::stateToDescription $state_code]]"
			}
		}
	}

	proc status { } {
		set nick [::abook::getPersonal MFN]
		write_remote "[trans nick]: $nick"
		if {[ ::config::getKey protocol] >= 11 } {
			set psm [::abook::getPersonal PSM]
			write_remote "[trans PSM]: $psm"
		}
		getstate
	}

	proc getstate { } {

		set my_state [::MSN::stateToDescription [::MSN::myStatusIs]]

		write_remote "Your state is currently on : $my_state"

	}

	proc setstate { {state ""} } {
		if { "$state" == "" } {
			write_remote "Possible status are :"
			write_remote " online, away, busy, noactivity, brb, onphone, lunch, appearoffline"
			return
		}

		set state [string tolower $state]
		if { "$state" == "online" } {
			ChCustomState NLN
		} elseif { "$state" == "away" } {
			ChCustomState AWY
		} elseif { "$state" == "busy" } {
			ChCustomState BSY
		} elseif { "$state" == "noactivity" } {
			ChCustomState IDL
		} elseif { "$state" == "brb" } {
			ChCustomState BRB
		} elseif { "$state" == "onphone" } {
			ChCustomState PHN
		} elseif { "$state" == "lunch" } {
			ChCustomState LUN
		} elseif { "$state" == "appearoffline" } {
			ChCustomState HDN
		} else {
			write_remote "Invalid state" error
			return
		}
		write_remote "State changed"
	}
	proc listcustomstates { } { 
		set numstates [StateList size] 
		
		if {$numstates > 0} { 
			write_remote "ID\tState name" 
			
			for { set stateid 0 } { $stateid < $numstates } { incr stateid } { 
				set state [StateList get $stateid] 
				write_remote "$stateid\t [lindex $state 0]" 
			} 
		} else { 
			write_remote "No custom states defined" 
		} 
	} 
	
	proc setcustomstate { state } { 
		set numstates [StateList size] 
		
		if { [string is digit $state] != 1 || $state < 0 || $state >= $numstates } { 
			write_remote "Invalid state" 
		} else { 
			ChCustomState $state 
		} 
	} 
	

       proc setpsm { args } { 
	       set psm [string map { \\\; \; \\\" \" \\\[ \[ \\\] \] \\\: \: \\\\ \\ \\\* \* \\\? \?} [join $args]]

	       ::MSN::changePSM "$psm" 
	       write_remote "PSM set to : $psm" 
       } 

	proc setnick { args } {
	       set nickname [string map { \\\; \; \\\" \" \\\[ \[ \\\] \] \\\: \: \\\\ \\ \\\* \* \\\? \?} [join $args]]
		if {$nickname != ""} {
			::MSN::changeName "$nickname"
			write_remote "New nick set to : $nickname"
		} else {
			write_remote "New nick not entered"
		}
	}

	proc amsn_close { } {
		exit
	}

	proc whois { user } {

		set found 0

		foreach username [::MSN::getList FL] {
			if { "[::abook::getNick $username]" == "$user" } {
				write_remote "$user is : $username" 
				set found 1
				break
			}
		}
		if { $found == 0 } {
			write_remote "$user was not found in your contact list..." error
		}
	}

	proc whatis { user } {

		set found 0

		if { [string match "*@*" $user] == 0 } {
			set user [split $user "@"]
			set user "[lindex $user 0]@hotmail.com"
			set user [string tolower $user]
		}	

		foreach username [::MSN::getList FL] {
			if { "$username" == "$user" } {
				write_remote "$user is known as : [::abook::getNick $user]" 
				set found 1
				break
			}
		}
		if { $found == 0 } {
			write_remote "$user was not found in your contact list..." error
		}
	}

	# msg { args }
	# sends a message to a user
	#
	proc msg { args } {
		global userchatto

		if { [info exists userchatto] } {
			set user "$userchatto"
			set message [string map { \\\; \; \\\" \" \\\[ \[ \\\] \] \\\: \: \\\\ \\ \\\* \* \\\? \?} [join $args]]
		} else {
			# This is to skip all the spaces that could be put before the user, like for example "msg       user1  my msg".
			# with the [split] we would get {msg {} {} {} {} {} {} user1 my msg}
			set idx 0
			set user {}
			while { [string length $user] <= 0 } {
				set user [lindex $args $idx]
				incr idx
			}
			set message [string map { \\\; \; \\\" \" \\\[ \[ \\\] \] \\\: \: \\\\ \\ \\\* \* \\\? \?} [join [lrange $args $idx end]]]
		}

		set message [string map { \{ "" \} ""} $message]

		if { [string match "*@*" $user] == 0 } {
			set user [split $user "@"]
			set user "[lindex $user 0]@hotmail.com"
		}

		set lowuser [string tolower $user]
   
		set win_name [::ChatWindow::For $lowuser]

		if { $win_name == 0 } {
			::amsn::chatUser "$user"

			while { [set win_name [::ChatWindow::For $lowuser]] == 0 } { }
		}

		#set input "${win_name}.f.bottom.in.input"
		set input [text ${win_name}.tmp]
		$input insert end "${message}"
	
		::amsn::MessageSend $win_name $input 
	
		destroy $input
	
	}

	proc chatto { user } { 
		global userchatto
	
		if { [string match "*@*" $user] == 0 } {
			set user [split $user "@"]
			set user "[lindex $user 0]@hotmail.com"
		}

		set userchatto "$user"

	}

	proc endchat { } {
		global userchatto
		if { [info exists userchatto] } {
			unset userchatto
		}
	}

}

proc write_remote { dataout {colour "normal"} } {
	global remote_sock

	#set dataout [string map [list "\n" " $colour\n"]  $dataout]
  
	catch {puts $remote_sock [list $dataout $colour]}
}

proc read_remote { command sock } {
	global remote_auth remote_sock

	if { ![::config::getKey enableremote]} { 
		close $sock
		return
	} 	

	if { "$remote_sock" != "$sock" } {
		set remote_temp_sock $remote_sock
		init_remote $sock
		if {  $remote_auth == 1 } {
			write_remote "Remote controlling is already active"
			init_remote $remote_temp_sock
			return 0
		}
	}


	if {$command != ""} {
		#AIM-FIX: Make command a real quoted list, or it will raise
		#errors when containing braces
		set command [split $command]
		if { $remote_auth == 0 } {
			authenticate "$command" "$sock"
		} elseif { [catch {eval "::remote::$command" } res] } {
			write_remote "[trans syntaxerror] : $res" error
		}
	}
}


proc md5keygen { } { 
	set key [expr rand()]
	set key [expr {$key * 1000000}]

	return "$key"
}

proc authenticate { command sock } {
	global remotemd5key remote_auth remote_sock_lock remote_authtimer
	global userchatto

	if {$remote_authtimer} {
		after cancel [list remote_touchauthtimer]
		after 3000 [list remote_touchauthtimer]
		write_remote "wait"
		close $sock
		return
	}

	if { $command == "auth" } {
		set remotemd5key "[md5keygen]"
		write_remote "auth $remotemd5key"
	} elseif { [lindex $command 0] == "auth2" && [info exists remotemd5key] } {
		if { "[lindex $command 1]" ==  "[::md5::hmac $remotemd5key [list [::config::getKey remotepassword]]]" } {
			set remote_auth 1
			set remote_sock_lock $sock
			catch { unset userchatto }
			write_remote "Authentication successfull"
		} else {
			set remote_authtimer 1
			after 3000 [list remote_touchauthtimer]
			write_remote "Authentication failed"
		}	
		unset remotemd5key
	} else {
		write_remote "[trans syntaxerror] : $command" error
	}
}


proc init_remote { sock } {
	global remote_sock

	set remote_sock $sock
}

proc close_remote { sock } {
	global remote_sock_lock remote_auth

	if { $remote_sock_lock == $sock } {
		set remote_auth 0
	} 
}

proc init_remote_DS { } {
	catch {socket -server new_remote_DS 63251}
}

proc new_remote_DS { sock addr port } {

	fileevent $sock readable "remote_DS_Hdl $sock"
	fconfigure $sock -buffering line
}

proc remote_DS_Hdl { sock } {

	set email [gets $sock]
	if {[eof $sock]} {
		catch {close $sock}
	} else {
		grep $email $sock
	}
}

proc grep { pattern sock } {
	global HOME2

	set filename "[file join $HOME2 profiles]"

	if { [string match "*@*" $pattern] == 0 } {
		set pattern [split $pattern "@"]
		set pattern "[lindex $pattern 0]@hotmail.com"
	}

	if {([file readable "$filename"] != 0) && ([file isfile "$filename"] != 0)} {
	
		set file_id [open "$filename" r]
		gets $file_id tmp_data
		if {$tmp_data != "amsn_profiles_version 1"} {	;# config version not supported!
			puts $sock "versionerror"
			close $file_id
			return 0
	   	}

		# Now add profiles from file to list
		while {[gets $file_id tmp_data] != "-1"} {
			set temp_data [split $tmp_data]
			if { [lindex $temp_data 0] == "$pattern" }  {
				close $file_id
				puts $sock "[lindex $temp_data 1]"
				return 1
			}
		}
		puts $sock "invalid"
		close $file_id
		return 0
	} else {
		puts $sock "noexist"
		return 0
	}
}