2003-ts6.tcl (45367B)
1 #source nda.tcl 2 #source 9999-protocol-common.tcl 3 4 5 namespace eval ts6 { 6 #proc putcmdlog {args} {} 7 proc ::ts6::b64e {numb} { 8 set b64 [split "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" {}] 9 10 set res "" 11 while {$numb != 0} { 12 append res [lindex $b64 [expr {$numb % 36}]] 13 set numb [expr {$numb / 36}] 14 } 15 if {[string length $res] == 0} { 16 set res "A" 17 } 18 return [string reverse $res] 19 } 20 21 proc ::ts6::b64d {numb} { 22 set b64 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" 23 set numb [string trimleft $numb "A"] 24 set res 0 25 for {set i 0} {$i<[string length $numb]} {incr i} { 26 set new [string first [string index $numb $i] $b64] 27 incr res [expr {$new * (36 * $i)+1}] 28 } 29 return $res 30 } 31 } 32 33 proc putl {args} { 34 puts stdout [join $args " "] 35 puts {*}$args 36 } 37 38 namespace eval ts6 { 39 40 proc ::ts6::sendUid {sck nick ident host dhost uid {realname "* Unknown *"} {modes "+oiS"} {server ""}} { 41 if {""==$server} {set server $::sid($sck)} 42 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $server]]}]] 43 append sid [::ts6::b64e $server] 44 set sendid [::ts6::b64e $uid] 45 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 46 append sendnn $sendid 47 if {![tnda get "netinfo/$::netname($sck)/euid"]} { 48 set sl [format ":%s UID %s 1 %s %s %s %s 0 %s%s :%s" $sid $nick [clock format [clock seconds] -format %s] $modes $ident $host $sid $sendnn $realname] 49 } { 50 set sl [format ":%s EUID %s 1 %s %s %s %s 0 %s%s %s * :%s" $sid $nick [clock format [clock seconds] -format %s] $modes $ident $dhost $sid $sendnn $host $realname] 51 } 52 tnda set "login/$::netname($sck)/${sid}${sendnn}" "" 53 tnda set "oper/$::netname($sck)/${sid}${sendnn}" [expr {[string first "o" $modes] != -1 ? 1 : 0}] 54 tnda set "metadata/$::netname($sck)/${sid}${sendnn}" [list] 55 tnda set "certfps/$::netname($sck)/${sid}${sendnn}" "" 56 tnda set "intclient/$::netname($sck)/${sid}${sendnn}" $uid 57 tnda set "nick/$::netname($sck)/${sid}${sendnn}" $nick 58 tnda set "ident/$::netname($sck)/${sid}${sendnn}" $ident 59 tnda set "rhost/$::netname($sck)/${sid}${sendnn}" $host 60 tnda set "vhost/$::netname($sck)/${sid}${sendnn}" $dhost 61 tnda set "rname/$::netname($sck)/${sid}${sendnn}" $realname 62 tnda set "ipaddr/$::netname($sck)/${sid}${sendnn}" 0 63 putl $sck $sl 64 } 65 66 proc ::ts6::topic {sck uid targ topic} { 67 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 68 append sid [::ts6::b64e $::sid($sck)] 69 set sendid [::ts6::b64e $uid] 70 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 71 append sendnn $sendid 72 putl $sck [format ":%s%s TOPIC %s :%s" $sid $sendnn $targ $topic] 73 } 74 75 proc ::ts6::setnick {sck uid newnick} { 76 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 77 append sid [::ts6::b64e $::sid($sck)] 78 set sendid [::ts6::b64e $uid] 79 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 80 append sendnn $sendid 81 putl $sck [format ":%s%s NICK %s :%s" $sid $sendnn $newnick [clock format [clock seconds] -format %s]] 82 } 83 84 proc ::ts6::sethost {sck targ topic} { 85 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 86 append sid [::ts6::b64e $::sid($sck)] 87 if {![tnda get "netinfo/$::netname($sck)/euid"]} { 88 putl $sck [format ":%s ENCAP * CHGHOST %s %s" $sid $targ $topic] 89 } { 90 putl $sck [format ":%s CHGHOST %s %s" $sid $targ $topic] 91 } 92 } 93 94 proc ::ts6::sendSid {sck sname sid {realname "In use by Services"}} { 95 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 96 append sid [::ts6::b64e $::sid($sck)] 97 set sl [format ":%s SID %s 1 %s :%s" [::ts6::b64e $sid] $sname [::ts6::b64e $sid] $realname] 98 putl $sck $sl 99 } 100 101 proc ::ts6::privmsg {sck uid targ msg} { 102 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 103 append sid [::ts6::b64e $::sid($sck)] 104 set sendid [::ts6::b64e $uid] 105 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 106 append sendnn $sendid 107 putl $sck [format ":%s%s PRIVMSG %s :%s" $sid $sendnn $targ $msg] 108 } 109 110 proc ::ts6::snote {sck targ msg} { 111 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 112 append sid [::ts6::b64e $::sid($sck)] 113 set sendid [::ts6::b64e $uid] 114 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 115 append sendnn $sendid 116 putl $sck [format ":%s ENCAP * SNOTE %s :%s" $sid $sendnn $targ $msg] 117 } 118 119 proc ::ts6::metadata {sck targ direction type {msg ""}} { 120 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 121 append sid [::ts6::b64e $::sid($sck)] 122 if {[string toupper $direction] != "ADD" && [string toupper $direction] != "DELETE"} {putloglev d * "failed METADATA attempt (invalid arguments)";return} ;#no that didn't work 123 if {[string toupper $direction] == "ADD"} { 124 tnda set "metadata/$::netname($sck)/$targ/[ndaenc $type]" $msg 125 putl $sck [format ":%s ENCAP * METADATA %s %s %s :%s" $sid [string toupper $direction] $targ [string toupper $type] $msg] 126 } 127 if {[string toupper $direction] == "DELETE"} { 128 tnda unset "metadata/$::netname($sck)/$targ/[ndaenc $type]" 129 putl $sck [format ":%s ENCAP * METADATA %s %s :%s" $sid [string toupper $direction] $targ [string toupper $type]] 130 } 131 } 132 133 proc ::ts6::kick {sck uid targ tn msg} { 134 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 135 append sid [::ts6::b64e $::sid($sck)] 136 set sendid [::ts6::b64e $uid] 137 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 138 append sendnn $sendid 139 putl $sck [format ":%s%s KICK %s %s :%s" $sid $sendnn $targ $tn $msg] 140 } 141 142 proc ::ts6::notice {sck uid targ msg} { 143 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 144 set sendid [::ts6::b64e $uid] 145 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 146 append sendnn $sendid 147 putl $sck [format ":%s%s NOTICE %s :%s" $sid $sendnn $targ $msg] 148 } 149 150 proc ::ts6::part {sck uid targ msg} { 151 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 152 set sendid [::ts6::b64e $uid] 153 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 154 append sendnn $sendid 155 putl $sck [format ":%s%s PART %s :%s" $sid $sendnn $targ $msg] 156 set chan [ndaenc $targ] 157 tnda unset "userchan/$::netname($sck)/$sid$sendnn/$chan" 158 tnda unset "channels/$::netname($sck)/$chan/status/$sid$sendnn" 159 firellbind $sck part "-" "-" [ndadec $chan] ${sid}${sendnn} $msg 160 } 161 162 proc ::ts6::quit {sck uid msg} { 163 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 164 set sendid [::ts6::b64e $uid] 165 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 166 append sendnn $sendid 167 putl $sck [format ":%s%s QUIT :%s" $sid $sendnn $msg] 168 foreach {chan _} [tnda get "userchan/$::netname($sck)/${sid}${sendnn}"] { 169 #firellbind $sck part "-" "-" $sid$sendnn [ndadec $chan] $msg 170 firellbind $sck quit "-" "-" $sid$sendnn [ndadec $chan] $msg 171 tnda unset "userchan/$::netname($sck)/${sid}${sendnn}/$chan" 172 tnda unset "channels/$::netname($sck)/$chan/status/${sid}${sendnn}" 173 } 174 firellbind $sck nquit "-" "-" $sid$sendnn $msg 175 tnda unset "login/$::netname($sck)/${sid}${sendnn}" 176 tnda unset "nick/$::netname($sck)/${sid}${sendnn}" 177 tnda unset "intclient/$::netname($sck)/${sid}${sendnn}" 178 tnda set "oper/$::netname($sck)/${sid}${sendnn}" 0 179 tnda unset "ident/$::netname($sck)/${sid}${sendnn}" 180 tnda unset "rhost/$::netname($sck)/${sid}${sendnn}" 181 tnda unset "vhost/$::netname($sck)/${sid}${sendnn}" 182 tnda unset "rname/$::netname($sck)/${sid}${sendnn}" 183 tnda unset "ipaddr/$::netname($sck)/${sid}${sendnn}" 184 tnda set "metadata/$::netname($sck)/${sid}${sendnn}" [list] 185 tnda unset "certfps/$::netname($sck)/${sid}${sendnn}" 186 } 187 188 proc ::ts6::setacct {sck targ msg} { 189 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 190 if {[ts6 uid2nick $sck $targ] == ""} {return} 191 putl $sck [format ":%s ENCAP * SU %s %s" $sid $targ $msg] 192 tnda set "login/$::netname($sck)/$targ" $msg 193 } 194 195 proc ::ts6::grant {sck targ msg {fmult 65}} { 196 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 197 if {[ts6 uid2nick $sck $targ] == ""} {return} 198 putl $sck [format ":%s ENCAP * GRANT %s %s %s" $sid $targ $fmult $msg] 199 tnda set "oper/$::netname($sck)/$targ" 1 200 } 201 202 proc ::ts6::putmotd {sck targ msg} { 203 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 204 if {[ts6 uid2nick $sck $targ] == ""} {return} 205 putl $sck [format ":%s 372 %s :- %s" $sid $targ $msg] 206 } 207 208 proc ::ts6::putmotdend {sck targ} { 209 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 210 if {[ts6 uid2nick $sck $targ] == ""} {return} 211 putl $sck [format ":%s 376 %s :End of global MOTD." $sid $targ] 212 } 213 214 proc ::ts6::putmode {sck uid targ mode {parm ""} {ts ""}} { 215 if {$ts == ""} { 216 if {[set ts [tnda get "channels/$::netname($sck)/[ndaenc [string tolower $targ]]/ts"]] == ""} {return} ;#cant do it, doesnt exist 217 } 218 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 219 set sendid [::ts6::b64e $uid] 220 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 221 append sendnn $sendid 222 putl $sck [format ":%s" [set com [format "%s%s TMODE %s %s %s %s" $sid $sendnn $ts $targ $mode $parm]]] 223 set comd [split $com " "] 224 set ctr 4 225 set state 1 226 foreach {c} [split $mode {}] { 227 if {$c == "+"} { 228 set state 1 229 } elseif {$c == "-"} { 230 set state 0 231 } elseif {[string match [format "*%s*" $c] [tnda get "netinfo/$::netname($sck)/chmparm"]] || ($state&&[string match [format "*%s*" $c] [tnda get "netinfo/$::netname($sck)/chmpartparm"]])} { 232 [expr {$state?"::ts6::checkop":"::ts6::checkdeop"}] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] [lindex $comd [incr ctr]] 233 firellmbind $sck mode - [format "%s %s%s" [string tolower [lindex $comd 3]] [expr {$state ? "+" : "-"}] $c] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] [lindex $comd [incr ctr]] 234 } else { 235 [expr {$state?"::ts6::checkop":"::ts6::checkdeop"}] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] [lindex $comd [incr ctr]] 236 firellmbind $sck mode - [format "%s %s%s" [string tolower [lindex $comd 3]] [expr {$state ? "+" : "-"}] $c] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] "" 237 # firellmbind $sck mode "-" [expr {$state ? "+" : "-"}] $c [lindex $comd 0] [lindex $comd 3] "" 238 } 239 } 240 } 241 242 proc ::ts6::sendencap {sck uid targ args} { 243 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 244 if {[ts6 uid2nick $sck $targ] == ""} {return} 245 if {$uid == "-1"} { set sendnn ""} { 246 set sendid [::ts6::b64e $uid] 247 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 248 append sendnn $sendid 249 } 250 if {[string first " " [lindex $args end]] != -1} { 251 putl $sck [format ":%s%s ENCAP %s %s :%s" $sid $sendnn $targ [join [lrange $args 0 end-1] " "] [lindex $args end]] 252 } { 253 putl $sck [format ":%s%s ENCAP %s %s" $sid $sendnn $targ [join $args " "]] 254 } 255 } 256 257 proc ::ts6::putjoin {sck uid targ {ts ""}} { 258 if {$ts == ""} { 259 if {[set ts [tnda get "channels/$::netname($sck)/[ndaenc [string tolower $targ]]/ts"]] == ""} {set ts [clock format [clock seconds] -format %s]} 260 } 261 set sid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append sid [::ts6::b64e $::sid($sck)] 262 set sendid [::ts6::b64e $uid] 263 set sendnn [string repeat "A" [expr {6-[string length $sendid]}]] 264 append sendnn $sendid 265 putl $sck [format ":%s SJOIN %s %s + :%s%s" $sid $ts $targ $sid $sendnn] 266 set chan [ndaenc $targ] 267 tnda set "userchan/$::netname($sck)/$sid$sendnn/$chan" 1 268 # tnda set "channels/$::netname($sck)/$chan/status/[lindex $comd 0]" "" 269 } 270 271 proc ::ts6::validchan {sck channelname} { 272 if {[string is digit [string index $channelname 0]] && [string length $channelname] == 9} {return 0} ;# valid handle, not valid channel 273 if {[string first [string index $channelname 0] [tnda get "netinfo/$::netname($sck)/[ndaenc CHANTYPES]"]] != -1} {return 1} ;# could be valid channel, so let's just say yes 274 } 275 276 proc ::ts6::quitstorm {sck sid comment {doinit 1}} { 277 if {$doinit} {set splits [list $sid]} {set splits [list]} 278 foreach {sid64 sdesc} [tnda get "servers/$::netname($sck)"] { 279 # if the server doesn't have $sid as the uplink, continue 280 if {[dict get $sdesc uplink] != $sid} { 281 continue 282 } 283 # but if it does... they split and we should see who they're taking down 284 lappend splits [string toupper [ndadec $sid64]] 285 foreach {splitid} [::ts6::quitstorm $sck [ndadec $sid64] $comment 0] { 286 lappend splits $splitid 287 } 288 } 289 return $splits 290 } 291 292 proc ::ts6::irc-main {sck} { 293 global sid sock socksid 294 if {[eof $sck]} { 295 puts stdout "We're dead, folks. [clock format [clock seconds] -format {%Y%m%d %H:%M.%S}]" 296 # firellbind $sck evnt "-" "ts6.dead" $::netname($sck) $sck 297 firellbind $sck evnt "-" "dead" $::netname($sck) $sck 298 firellbind - evnt "-" "dead" $sck $::netname($sck) 299 close $sck 300 } 301 set ::errorInfo "" 302 gets $sck line 303 setctx $::netname($sck) 304 putloglev r * $line 305 set line [string trim $line "\r\n"] 306 set one [string match ":*" $line] 307 set line [string trimleft $line ":"] 308 set gotsplitwhere [string first " :" $line] 309 if {$gotsplitwhere==-1} {set comd [split $line " "]} {set comd [split [string range $line 0 [expr {$gotsplitwhere - 1}]] " "]} 310 if {$gotsplitwhere==-1} {set payload [lindex $comd end]} {set payload [string range $line [expr {$gotsplitwhere + 2}] end]} 311 if {$gotsplitwhere != -1} {lappend comd $payload} 312 if {[lindex $comd 0] == "PING"} {putl $sck "PONG $::snames($sck) :$payload"} 313 if {[lindex $comd 0] == "SERVER"} {putl $sck "VERSION"} 314 if {$one == 1} { 315 set sourceof [lindex $comd 0] 316 set two 2 317 } { set sourceof "" 318 set two 1} 319 firellbind $sck raw - [lindex $comd $one] $sourceof [lindex $comd $one] [join [lrange $comd $two end] " "] 320 set erreno [catch { 321 switch -nocase -- [lindex $comd $one] { 322 "479" {putloglev d * $payload} 323 "PASS" { 324 # putquick "PRIVMSG #services :$line" 325 #puts stdout "we have a winner! $one" 326 set ssid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append ssid [::ts6::b64e $::sid($sck)] 327 tnda set "servers/$::netname($sck)/[ndaenc [lindex $comd 4]]/uplink" $ssid 328 tnda set "servers/$::netname($sck)/[ndaenc [lindex $comd 4]]/sid" $payload 329 tnda set "socksid/$::netname($sck)" $payload 330 } 331 332 "SERVER" { 333 #puts stdout "we have a winner! $one" 334 # if {[lindex $comd [expr {$one + 2}]] != 1} {return};#we don't support jupes 335 tnda set "servers/$::netname($sck)/[ndaenc [tnda get "socksid/$::netname($sck)"]]/name" [lindex $comd [expr {$one + 1}]] 336 tnda set "servers/$::netname($sck)/[ndaenc [tnda get "socksid/$::netname($sck)"]]/description" [lindex $comd [expr {$one + 3}]] 337 # firellbind $sck evnt "-" "alive" $::netname($sck) 338 if {$one == 0} {firellbind - evnt "-" "alive" $::netname($sck)} 339 # firellbind $sck evnt "-" "ts6.alive" $::netname($sck) 340 } 341 342 "SID" { 343 #puts stdout "we have a winner! $one" 344 tnda set "servers/$::netname($sck)/[ndaenc [lindex $comd 4]]/name" [lindex $comd 2] 345 tnda set "servers/$::netname($sck)/[ndaenc [lindex $comd 4]]/description" [lindex $comd 5] 346 tnda set "servers/$::netname($sck)/[ndaenc [lindex $comd 4]]/uplink" [lindex $comd 0] 347 tnda set "servers/$::netname($sck)/[ndaenc [lindex $comd 4]]/sid" [lindex $comd 4] 348 # putloglev o * [tnda get "servers"] 349 } 350 351 "SQUIT" { 352 set ssid [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]];append ssid [::ts6::b64e $::sid($sck)] 353 set failedserver [lindex $comd [expr {$one + 1}]] 354 # is it us? 355 if {$failedserver == $ssid} { 356 #yes, it's us. 357 putloglev d * "We're dead, folks. [clock format [clock seconds] -format {%Y%m%d %H:%M:%S}]" 358 firellbind $sck evnt "-" "ts6.dead" $::netname($sck) 359 firellbind $sck evnt "-" "dead" $::netname($sck) 360 firellbind - evnt "-" "dead" $sck $::netname($sck) 361 return 362 } 363 # Mark all servers with an uplink in failedservers as split 364 set slist [::ts6::quitstorm $sck [lindex $comd [expr {$one + 1}]] [lindex $comd [expr {$one + 2}]]] 365 foreach {srv} $slist { 366 ::ts6::snote $sck x [format "!! NETSPLIT: %s (%s) has left the network (Server Quit: %s)" [tnda get "servers/$::netname($sck)/[ndaenc $srv]/name"] $srv [lindex $comd [expr {$one + 2}]] 367 tnda unset "servers/$::netname($sck)/[ndaenc $srv]" 368 foreach {uidd _} [tnda get "nick/$::netname($sck)"] { 369 if {[string range $uidd 0 2] != $srv} {continue};# not a dead user 370 foreach {chan _} [tnda get "userchan/$::netname($sck)/$uidd"] { 371 firellbind $sck part "-" "-" [ndadec $chan] $uidd $::netname($sck) 372 # firellbind $sck cquit "-" "-" [ndadec $chan] $uidd $::netname($sck) 373 tnda set "userchan/$::netname($sck)/$uidd/$chan" 0 374 } 375 376 ::ts6::snote $sck x [format "!! NETSPLIT: %s (%s) has quit due to netsplit (%s: %s)" [tnda get "nick/$::netname($sck)/$uidd"] $uidd [tnda get "servers/$::netname($sck)/[ndaenc $srv]/name"] [lindex $comd [expr {$one + 2}]] 377 tnda unset "login/$::netname($sck)/$uidd" 378 tnda unset "nick/$::netname($sck)/$uidd" 379 tnda set "oper/$::netname($sck)/$uidd" 0 380 tnda unset "ident/$::netname($sck)/$uidd" 381 tnda unset "rhost/$::netname($sck)/$uidd" 382 tnda unset "vhost/$::netname($sck)/$uidd" 383 tnda unset "rname/$::netname($sck)/$uidd" 384 tnda unset "ipaddr/$::netname($sck)/$uidd" 385 tnda set "metadata/$::netname($sck)/$uidd" [list] 386 tnda unset "certfps/$::netname($sck)/$uidd" 387 firellbind $sck quit "-" "-" $uidd $::netname($sck) 388 } 389 } 390 } 391 392 "005" - "105" { 393 foreach {tok} [lrange $comd 3 end] { 394 foreach {key val} [split $tok "="] { 395 if {$key == "PREFIX"} { 396 # We're in luck! Server advertises its PREFIX in VERSION reply to servers. 397 if {[tnda get "netinfo/$::netname($sck)/pfxissjoin"] == 1} {continue} 398 set v [string range $val 1 end] 399 set mod [split $v ")"] 400 set modechar [split [lindex $mod 1] {}] 401 set modepref [split [lindex $mod 0] {}] 402 foreach {c} $modechar {x} $modepref { 403 tnda set "netinfo/$::netname($sck)/prefix/$c" $x 404 } 405 foreach {x} $modechar {c} $modepref { 406 tnda set "netinfo/$::netname($sck)/pfxchar/$c" $x 407 } 408 } elseif {$key == "SJOIN"} { 409 # We're in luck! Server advertises its PREFIX in VERSION reply to servers. 410 tnda set "netinfo/$::netname($sck)/pfxissjoin" 1 411 set v [string range $val 1 end] 412 set mod [split $v ")"] 413 set modechar [split [lindex $mod 1] {}] 414 set modepref [split [lindex $mod 0] {}] 415 foreach {c} $modechar {x} $modepref { 416 tnda set "netinfo/$::netname($sck)/prefix/$c" $x 417 } 418 foreach {x} $modechar {c} $modepref { 419 tnda set "netinfo/$::netname($sck)/pfxchar/$c" $x 420 } 421 } elseif {$key == "CHANMODES"} { 422 set spt [split $val ","] 423 tnda set "netinfo/$::netname($sck)/chmban" [lindex $spt 0] 424 tnda set "netinfo/$::netname($sck)/chmparm" [format "%s%s" [lindex $spt 0] [lindex $spt 1]] 425 tnda set "netinfo/$::netname($sck)/chmpartparm" [lindex $spt 2] 426 tnda set "netinfo/$::netname($sck)/chmnoparm" [lindex $spt 3] 427 } else { 428 tnda set "netinfo/$::netname($sck)/[ndaenc $key]" $val 429 } 430 } 431 } 432 } 433 434 "PRIVMSG" { 435 if {[::ts6::validchan $sck [lindex $comd 2]]} { 436 set client chan 437 set words [split $payload " "] 438 set kword [lindex $words 0] 439 if {[string index $payload 0] == "\001"} { 440 set payload [string range $payload 1 end-1] 441 set words [split $payload " "] 442 set kword [lindex $words 0] 443 set payload [join [lrange $words 1 end] " "] 444 firellbind $sck ctcp - [string tolower $payload] [lindex $comd 0] [lindex $comd 2] $kword $payload 445 } { 446 set mpayload [join [lrange $words 1 end] " "] 447 firellbind $sck pub - [string tolower $payload] [lindex $comd 0] [lindex $comd 2] $mpayload 448 firellmbind $sck pubm - [string tolower $payload] [lindex $comd 0] [lindex $comd 2] $payload 449 } 450 #firellbind $sck notc "-" [string tolower [lindex [split $payload " "] 0]] [lindex $comd 2] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 451 #firellmbind $sck pnotcm $client [string tolower [lindex [split $payload " "] 0]] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 452 # firellbind $sck pubnotc-m "-" [string tolower [lindex [split $payload " "] 0]] [lindex $comd 2] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 453 firellbind $sck "evnt" "-" "chanmsg" [lindex $comd 0] [lindex $comd 2] $payload 454 } { 455 set client [tnda get "intclient/$::netname($sck)/[lindex $comd 2]"] 456 set words [split $payload " "] 457 set kword [lindex $words 0] 458 if {[string index $payload 0] == "\001"} { 459 set payload [string range $payload 1 end-1] 460 set words [split $payload " "] 461 set kword [lindex $words 0] 462 set payload [join [lrange $words 1 end] " "] 463 firellbind $sck ctcp - [string tolower $kword] [lindex $comd 0] [% uid2nick [lindex $comd 2]] $kword $payload 464 } { 465 set mpayload [join [lrange $words 1 end] " "] 466 firellbind $sck msg $client [string tolower $kword] [lindex $comd 0] $mpayload 467 firellmbind $sck msgm $client [string tolower $payload] [lindex $comd 0] $payload 468 } 469 #firellbind $sck notc $client [string tolower [lindex [split $payload " "] 0]] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 470 #firellmbind $sck notcm $client [string tolower [lindex [split $payload " "] 0]] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 471 firellbind $sck "evnt" "-" "privmsg" [lindex $comd 0] [lindex $comd 2] $payload 472 } 473 } 474 475 "NOTICE" { 476 if {0==[tnda get "netinfo/$::netname($sck)/connected"]} {} { 477 if {[::ts6::validchan $sck [lindex $comd 2]]} { 478 set client chan 479 if {[string index $payload 0] == "\001"} { 480 set payload [string range $payload 1 end-1] 481 set words [split $payload " "] 482 set kword [lindex $words 0] 483 set payload [join [lrange $words 1 end] " "] 484 firellbind $sck ctcr - [string tolower $payload] [lindex $comd 0] [lindex $comd 2] $kword $payload 485 } { 486 firellmbind $sck notc - [string tolower $payload] [lindex $comd 0] [lindex $comd 2] $payload 487 } 488 #firellbind $sck notc "-" [string tolower [lindex [split $payload " "] 0]] [lindex $comd 2] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 489 #firellmbind $sck pnotcm $client [string tolower [lindex [split $payload " "] 0]] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 490 # firellbind $sck pubnotc-m "-" [string tolower [lindex [split $payload " "] 0]] [lindex $comd 2] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 491 #firellbind $sck "evnt" "-" "channotc" [lindex $comd 0] [lindex $comd 2] $payload 492 } { 493 set client [tnda get "intclient/$::netname($sck)/[lindex $comd 2]"] 494 if {[string index $payload 0] == "\001"} { 495 set payload [string range $payload 1 end-1] 496 set words [split $payload " "] 497 set kword [lindex $words 0] 498 set payload [join [lrange $words 1 end] " "] 499 firellbind $sck ctcr - [string tolower $payload] [lindex $comd 0] [% uid2nick [lindex $comd 2]] $kword $payload 500 } { 501 firellmbind $sck notc - [string tolower $payload] [lindex $comd 0] [% uid2nick [lindex $comd 2]] $payload 502 } 503 #firellbind $sck notc $client [string tolower [lindex [split $payload " "] 0]] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 504 #firellmbind $sck notcm $client [string tolower [lindex [split $payload " "] 0]] [lindex $comd 0] [join [lrange [split $payload " "] 1 end] " "] 505 #firellbind $sck "evnt" "-" "privnotc" [lindex $comd 0] [lindex $comd 2] $payload 506 } 507 } 508 } 509 510 "MODE" { 511 if {[lindex $comd 2] == [tnda get "nick/$::netname($sck)/[lindex $comd 0]"] || [lindex $comd 2] == [lindex $comd 0]} { 512 foreach {c} [split [lindex $comd 3] {}] { 513 switch -- $c { 514 "+" {set state 1} 515 "-" {set state 0} 516 "o" {tnda set "oper/$::netname($sck)/[lindex $comd 0]" $state} 517 } 518 } 519 } 520 } 521 522 "JOIN" { 523 set chan [string map {/ [} [::base64::encode [string tolower [lindex $comd 3]]]] 524 if {""==[tnda get "channels/$::netname($sck)/$chan/ts"]} {firellbind $sck create "-" "-" [lindex $comd 3] [lindex $comd 0] $::netname($sck)} 525 # firellbind $sck join "-" "-" [lindex $comd 3] [lindex $comd 0] $::netname($sck) 526 firellmbind $sck join - [format "%s %s!%s@%s" [lindex $comd 3] [% uid2nick [lindex $comd 0]] [% uid2ident [lindex $comd 0]] [% uid2host [lindex $comd 0]]] [lindex $comd 0] [lindex $comd 3] 527 tnda set "channels/$::netname($sck)/$chan/ts" [lindex $comd 2] 528 tnda set "userchan/$::netname($sck)/[lindex $comd 0]/$chan" 1 529 } 530 531 "BMASK" { 532 # always +, no ctr and no state 533 set adding [split $payload " "] 534 set chan [ndaenc [lindex $comd 3]] 535 if {[lindex $comd 2] > [tnda get "channels/$::netname($sck)/$chan/ts"]} {return} ;# send it packing. 536 set type [lindex $comd 4] 537 foreach {mask} $adding { 538 ::ts6::checkop [lindex $comd 0] [lindex $comd 3] [format "%s%s" + $type] $mask 539 firellmbind $sck mode - [format "%s +%s" [lindex $comd 3] $type] [lindex $comd 0] [lindex $comd 3] "+$type" $mask 540 #+ $type [lindex $comd 0] [lindex $comd 3] $mask $::netname($sck) 541 } 542 } 543 544 "TMODE" { 545 set ctr 4 546 set state 1 547 foreach {c} [split [lindex $comd 4] {}] { 548 if {$c == "+"} { 549 set state 1 550 } elseif {$c == "-"} { 551 set state 0 552 } elseif {[string match [format "*%s*" $c] [tnda get "netinfo/$::netname($sck)/chmparm"]] || ($state&&[string match [format "*%s*" $c] [tnda get "netinfo/$::netname($sck)/chmpartparm"]])} { 553 [expr {$state?"::ts6::checkop":"::ts6::checkdeop"}] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] [lindex $comd [incr ctr]] 554 firellmbind $sck mode - [format "%s %s%s" [string tolower [lindex $comd 3]] [expr {$state ? "+" : "-"}] $c] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] [lindex $comd [incr ctr]] 555 } else { 556 [expr {$state?"::ts6::checkop":"::ts6::checkdeop"}] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] [lindex $comd [incr ctr]] 557 firellmbind $sck mode - [format "%s %s%s" [string tolower [lindex $comd 3]] [expr {$state ? "+" : "-"}] $c] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] "" 558 # firellmbind $sck mode "-" [expr {$state ? "+" : "-"}] $c [lindex $comd 0] [lindex $comd 3] "" 559 } 560 } 561 } 562 563 "SJOIN" { 564 set chan [ndaenc [lindex $comd 3]] 565 if {[string index [lindex $comd 4] 0] == "+"} { 566 set four 5 567 set ctr 4 568 if {[string match "*l*" [lindex $comd 4]]} {incr four} 569 if {[string match "*f*" [lindex $comd 4]]} {incr four} 570 if {[string match "*j*" [lindex $comd 4]]} {incr four} 571 if {[string match "*k*" [lindex $comd 4]]} {incr four} 572 foreach {c} [split [lindex $comd 4] {}] { 573 if {$c == "+"} { 574 set state 1 575 } elseif {$c == "-"} { 576 # _NOTREACHED 577 set state 0 578 } elseif {[string match [format "*%s*" $c] [tnda get "netinfo/$::netname($sck)/chmparm"]] || ($state&&[string match [format "*%s*" $c] [tnda get "netinfo/$::netname($sck)/chmpartparm"]])} { 579 putloglev d * "check(de)op with parameter" 580 [expr {$state?"::ts6::checkop":"::ts6::checkdeop"}] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] [lindex $comd [incr ctr]] 581 firellmbind $sck mode - [format "%s %s%s" [string tolower [lindex $comd 3]] [expr {$state ? "+" : "-"}] $c] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] [lindex $comd [incr ctr]] 582 } else { 583 putloglev d * "check(de)op without parameter" 584 [expr {$state?"::ts6::checkop":"::ts6::checkdeop"}] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] "" 585 firellmbind $sck mode - [format "%s %s%s" [string tolower [lindex $comd 3]] [expr {$state ? "+" : "-"}] $c] [lindex $comd 0] [lindex $comd 3] [format "%s%s" [expr {$state?"+":"-"}] $c] "" 586 # firellmbind $sck mode "-" [expr {$state ? "+" : "-"}] $c [lindex $comd 0] [lindex $comd 3] "" 587 } 588 } 589 } { 590 set four 4 591 } 592 tnda set "channels/$::netname($sck)/$chan/ts" [lindex $comd 2] 593 # XXX: some servers don't give their SJOIN prefixes in PREFIX. 594 # Solution? irca will, from the next release, support 005 portion "SJOIN=" formatted same as 595 # PREFIX. 596 # Also allow hardcoding. 597 foreach {nick} [split $payload " "] { 598 set un "" 599 set uo "" 600 set state uo 601 set un [string range $nick end-8 end] 602 set uo [string map [tnda get "netinfo/$::netname($sck)/prefix"] [string range $nick 0 end-9]] 603 # foreach {c} [split $nick {}] { 604 # if {[string is digit $c]} {set state un} 605 # if {$state == "uo"} {set c [tnda get "netinfo/$::netname($sck)/prefix/$c"] ; } 606 # if {"un"==$state} {append un $c} 607 # if {"uo"==$state} {append uo $c} 608 # } 609 putloglev j [ndadec $chan] [format "JOIN %s by nicknumber %s (nick %s, modes %s)" [ndadec $chan] $nick [tnda get "nick/$::netname($sck)/$un"] $uo] 610 # firellbind $sck join "-" "-" [lindex $comd 3] $un $::netname($sck) 611 firellmbind $sck join - [format "%s %s!%s@%s" [lindex $comd 3] [% uid2nick $un] [% uid2ident $un] [% uid2host $un]] $un [lindex $comd 3] 612 tnda set "userchan/$::netname($sck)/$un/$chan" 1 613 if {""!=$uo} {tnda set "channels/$::netname($sck)/$chan/status/$un" $uo 614 foreach {c} [split $uo {}] { 615 ::ts6::checkop [lindex $comd 0] [lindex $comd 3] [format "%s%s" + $c] $un 616 firellmbind $sck mode - [format "%s +%s" [lindex $comd 3] $c] [lindex $comd 0] [lindex $comd 3] "+$c" $un 617 # firellbind $sck mode "-" + $c $un [lindex $comd 3] $un $::netname($sck) 618 } 619 } 620 } 621 622 } 623 624 "PART" { 625 set un [lindex $comd 0] 626 firellmbind $sck part - [format "%s %s!%s@%s" [lindex $comd 2] [% uid2nick $un] [% uid2ident $un] [% uid2host $un]] $un [lindex $comd 2] [lindex $comd 3] 627 firellbind $sck part "-" "-" [lindex $comd 2] [lindex $comd 0] [lindex $comd 3] 628 set chan [string map {/ [} [::base64::encode [string tolower [lindex $comd 2]]]] 629 foreach {c} [split [tnda get "channels/$::netname($sck)/$chan/status/[lindex $comd 0]"] {}] { 630 ::ts6::checkdeop [lindex $comd 0] [ndadec $chan] -$c [lindex $comd 0] 631 } 632 tnda unset "userchan/$::netname($sck)/[lindex $comd 0]/$chan" 633 tnda unset "channels/$::netname($sck)/$chan/status/[lindex $comd 0]" 634 } 635 636 "KICK" { 637 firellbind $sck kick "-" "-" [lindex $comd 2] [lindex $comd 3] [lindex $comd 4] 638 set chan [string map {/ [} [::base64::encode [string tolower [lindex $comd 2]]]] 639 foreach {c} [split [tnda get "channels/$::netname($sck)/$chan/status/[lindex $comd 3]"] {}] { 640 ::ts6::checkdeop [lindex $comd 0] [ndadec $chan] -$c [lindex $comd 3] 641 } 642 tnda unset "userchan/$::netname($sck)/[lindex $comd 3]/$chan" 643 tnda unset "channels/$::netname($sck)/$chan/status/[lindex $comd 3]" 644 } 645 646 "NICK" { 647 firellmbind $sck nick "-" [format "%s %s" "*" [lindex $comd 2]] [lindex $comd 0] "*" [lindex $comd 2] 648 tnda set "nick/$::netname($sck)/[lindex $comd 0]" [lindex $comd 2] 649 tnda set "ts/$::netname($sck)/[lindex $comd 0]" [lindex $comd 3] 650 } 651 652 "EUID" { 653 set num 9 654 set ctr 1 655 set oper 0 656 set loggedin [lindex $comd 11] 657 set realhost [lindex $comd 10] 658 set modes [lindex $comd 5] 659 # puts stdout $comd 660 # puts stdout $modes 661 if {[string first "o" $modes] != -1} {set oper 1} 662 tnda set "login/$::netname($sck)/[lindex $comd $num]" "" 663 if {"*"!=$loggedin} { 664 tnda set "login/$::netname($sck)/[lindex $comd $num]" $loggedin 665 } 666 if {"*"!=$realhost} { 667 tnda set "rhost/$::netname($sck)/[lindex $comd $num]" $realhost 668 } { 669 tnda set "rhost/$::netname($sck)/[lindex $comd $num]" [lindex $comd 7] 670 } 671 tnda set "nick/$::netname($sck)/[lindex $comd $num]" [lindex $comd 2] 672 tnda set "oper/$::netname($sck)/[lindex $comd $num]" $oper 673 tnda set "ident/$::netname($sck)/[lindex $comd $num]" [lindex $comd 6] 674 tnda set "vhost/$::netname($sck)/[lindex $comd $num]" [lindex $comd 7] 675 tnda set "ipaddr/$::netname($sck)/[lindex $comd $num]" [lindex $comd 8] 676 tnda set "ts/$::netname($sck)/[lindex $comd $num]" [lindex $comd 4] 677 tnda set "rname/$::netname($sck)/[lindex $comd $num]" $payload 678 #putloglev j * [format "New user at %s %s %s!%s@%s (IP address %s, vhost %s) :%s" $::netname($sck) [lindex $comd $num] [lindex $comd 2] [lindex $comd 6] [tnda get "rhost/$::netname($sck)/[lindex $comd $num]"] [lindex $comd 8] [tnda get "vhost/$::netname($sck)/[lindex $comd $num]"] $payload] 679 firellbind $sck conn "-" "-" [lindex $comd $num] 680 } 681 682 "KLINE" {putloglev k * [format "KLINE: %s" $line]} 683 "BAN" {putloglev k * [format "BAN: %s" $line]} 684 685 "ENCAP" { 686 switch -nocase -- [lindex $comd 3] { 687 "SASL" { 688 # we have to support sasl messages, so... 689 firellbind $sck encap - "sasl" [lrange $comd 4 end] 690 #don't bother 691 } 692 "KLINE" { 693 putloglev k * [format "KLINE: %s" $line] 694 } 695 "SU" { 696 if {$payload == ""} {set payload [lindex $comd 5]} 697 tnda set "login/$::netname($sck)/[lindex $comd 4]" $payload 698 if {$payload == ""} {firellbind $sck logout "-" "-" [lindex $comd 4]} {firellbind $sck login "-" "-" [lindex $comd 4] $payload} 699 } 700 "CERTFP" { 701 tnda set "certfps/$::netname($sck)/[lindex $comd 0]" $payload 702 firellbind $sck encap "-" "certfp" [lindex $comd 0] $payload 703 } 704 "METADATA" { 705 switch -nocase -- [lindex $comd 4] { 706 "ADD" { 707 tnda set "metadata/$::netname($sck)/[lindex $comd 5]/[ndcenc [lindex $comd 6]]" $payload 708 firellbind $sck encap "-" "metadata.[string tolower [lindex $comd 6]]" [lindex $comd 5] $payload 709 firellbind $sck mark "-" [lindex $comd 6] [lindex $comd 5] $payload 710 } 711 "DELETE" { 712 tnda unset "metadata/$::netname($sck)/[lindex $comd 5]/[ndcenc $payload]" 713 firellbind $sck encap "-" "metadata.[string tolower $payload]" [lindex $comd 5] "" 714 firellbind $sck mark "-" $payload [lindex $comd 5] "" 715 # WARNING!!!! Pick ONE. The official scripts use MARK; you should too. 716 } 717 } 718 } 719 } 720 } 721 722 "TOPIC" { 723 firellbind $sck topic "-" "-" [lindex $comd 2] [join $payload " "] 724 } 725 "QUIT" { 726 if {![string is digit [string index [lindex $comd 0] 0]]} { 727 set ocomd [lrange $comd 1 end] 728 set on [lindex $comd 0] 729 set comd [list [::ts6::nick2uid $::netname($sck) $on] {*}$ocomd] 730 putloglev k * [format "Uh-oh, netsplit! %s -> %s has split" $on [::ts6::nick2uid $::netname($sck) $on]] 731 } 732 foreach {chan _} [tnda get "userchan/$::netname($sck)/[lindex $comd 0]"] { 733 putloglev d * "$chan -> [ndadec $chan]" 734 putloglev d * "[cdbase get channels $::netname($sck) $chan]" 735 foreach {c} [split [cdbase get channels $::netname($sck) $chan status [lindex $comd 0]] {}] { 736 ::ts6::checkdeop [lindex $comd 0] [ndadec $chan] -$c [lindex $comd 0] 737 #puts stdout $::errorInfo 738 } 739 firellbind $sck quit "-" "-" [lindex $comd 0] [ndadec $chan] $::netname($sck) 740 tnda unset "userchan/$::netname($sck)/[lindex $comd 0]/$chan" 741 #tnda unset "channels/$::netname($sck)/$chan/status/[lindex $comd 0]" 742 } 743 744 tnda unset "login/$::netname($sck)/[lindex $comd 0]" 745 tnda unset "nick/$::netname($sck)/[lindex $comd 0]" 746 tnda unset "oper/$::netname($sck)/[lindex $comd 0]" 747 tnda unset "ident/$::netname($sck)/[lindex $comd 0]" 748 tnda unset "rhost/$::netname($sck)/[lindex $comd 0]" 749 tnda unset "vhost/$::netname($sck)/[lindex $comd 0]" 750 tnda unset "rname/$::netname($sck)/[lindex $comd 0]" 751 tnda unset "ipaddr/$::netname($sck)/[lindex $comd 0]" 752 tnda unset "metadata/$::netname($sck)/[lindex $comd 0]" 753 tnda unset "certfps/$::netname($sck)/[lindex $comd 0]" 754 firellbind $sck nquit - - [lindex $comd 0] $payload 755 } 756 757 "KILL" { 758 foreach {chan _} [tnda get "userchan/$::netname($sck)/[lindex $comd 2]"] { 759 firellbind $sck quit "-" "-" [lindex $comd 2] [ndadec $chan] $payload 760 tnda set "userchan/$::netname($sck)/[lindex $comd 2]/$chan" 0 761 } 762 tnda unset "login/$::netname($sck)/[lindex $comd 2]" 763 tnda unset "nick/$::netname($sck)/[lindex $comd 2]" 764 tnda unset "oper/$::netname($sck)/[lindex $comd 2]" 765 tnda unset "ident/$::netname($sck)/[lindex $comd 2]" 766 tnda unset "ipaddr/$::netname($sck)/[lindex $comd 2]" 767 tnda unset "rhost/$::netname($sck)/[lindex $comd 2]" 768 tnda unset "vhost/$::netname($sck)/[lindex $comd 2]" 769 tnda unset "rname/$::netname($sck)/[lindex $comd 2]" 770 tnda unset "metadata/$::netname($sck)/[lindex $comd 2]" 771 tnda unset "certfps/$::netname($sck)/[lindex $comd 2]" 772 #firellbind $sck nquit - - [lindex $comd 2] $payload 773 firellbind $sck nkill - - [lindex $comd 0] [lindex $comd 2] $payload 774 } 775 776 "ERROR" { 777 putloglev s * "Recv'd an ERROR $payload from $::netname($sck)" 778 } 779 780 "WHOIS" { 781 # Usually but not always for a local client. 782 set num [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 783 append num [::ts6::b64e $::sid($sck)] 784 set targ [::ts6::nick2uid $::netname($sck) $payload] 785 if {[tnda get "nick/$::netname($sck)/$targ"] == ""} { 786 putl $sck [format ":%s 401 %s %s :No such user." $num [lindex $comd 0] $payload] 787 } else { 788 putl $sck [format ":%s 311 %s %s %s %s * :%s" $num [lindex $comd 0] [tnda get "nick/$::netname($sck)/$targ"] [tnda get "ident/$::netname($sck)/$targ"] [tnda get "vhost/$::netname($sck)/$targ"] [tnda get "rname/$::netname($sck)/$targ"]] 789 } 790 putl $sck [format ":%s 318 %s %s :End of /WHOIS list." $num [lindex $comd 0] $payload] 791 } 792 793 "CAPAB" { 794 tnda set "netinfo/$::netname($sck)/euid" 0 795 foreach {cw} [split $payload " "] { 796 if {$cw == "EUID"} {tnda set "netinfo/$::netname($sck)/euid" 1} 797 } 798 tnda set "netinfo/$::netname($sck)/connected" 1 799 } 800 801 "PING" { 802 set num [string repeat "0" [expr {3-[string length [::ts6::b64e $::sid($sck)]]}]] 803 append num [::ts6::b64e $::sid($sck)] 804 if {[lindex $comd 3]==""} {set pong [lindex $comd 0]} {set pong [lindex $comd 3]} 805 putl $sck [format ":%s PONG %s %s" $num $pong [lindex $comd 2]] 806 } 807 } 808 } erreur erropts] 809 if {$erreno != 0} {putloglev d * [format "error code %s, output %s while processing %s" $erreno $erreur [join $comd " "]] 810 foreach {li} [split [dict get $erropts -errorinfo] "\r\n"] { 811 putloglev d * [format "error info: %s" $li] 812 } 813 } 814 } 815 816 # irrelevant parameters should simply be ignored. 817 proc ::ts6::login {sck {osid "42"} {password "link"} {servname "net"} {servername services.invalid} {cfg {}}} { 818 set num [string repeat "0" [expr {3-[string length [::ts6::b64e $osid]]}]] 819 append num [::ts6::b64e $osid] 820 global netname sid sock nettype socksid snames 821 lassign [list 1 "Unconfigured"] useeuid gecos 822 dictassign $cfg euid useeuid gecos gecos 823 set snames($sck) $servername 824 set netname($sck) $servname 825 set nettype($servname) ts6 826 set sock($servname) $sck 827 set sid($sck) $osid 828 set sid($servname) $osid 829 tnda set "netinfo/$::netname($sck)/connected" 0 830 tnda set "netinfo/$::netname($sck)/euid" 0 831 #if {$halfops == ""} {tnda set "pfx/halfop" v} {tnda set "pfx/halfop" $halfops} 832 #if {![info exists ::ts6(ownermode)]} {tnda set "pfx/owner" o} {tnda set "pfx/owner" $ownermode)} 833 #if {![info exists ::ts6(protectmode)]} {tnda set "pfx/protect" o} {tnda set "pfx/protect" $protectmode} 834 if {$useeuid == ""} {tnda set "netinfo/$::netname($sck)/euid" 1} {tnda set "netinfo/$::netname($sck)/euid" $useeuid} 835 836 putl $sck [format "PASS %s TS 6 :%s" $password $num] 837 putl $sck "CAPAB :UNKLN BAN KLN RSFNC EUID ENCAP IE EX CLUSTER EOPMOD SVS SERVICES QS" 838 putl $sck [format "SERVER %s 1 :%s" $servername $gecos] 839 putl $sck [format "SVINFO 6 6 0 :%s" [clock format [clock seconds] -format %s]] 840 putl $sck [format ":%s VERSION" $num] 841 # llbind $sck mode - "* +*" ::ts6::checkop 842 # llbind $sck mode - "* -*" ::ts6::checkdeop 843 844 chan event $sck readable [list ::ts6::irc-main $sck] 845 } 846 847 #source services.conf 848 849 proc ::ts6::nick2uid {sck nick} { 850 foreach {u n} [tnda get "nick/$::netname($sck)"] { 851 if {[string tolower $n] == [string tolower $nick]} {return $u} 852 } 853 return "" 854 } 855 proc ::ts6::intclient2uid {sck nick} { 856 foreach {u n} [tnda get "intclient/$::netname($sck)"] { 857 if {[string tolower $n] == [string tolower $nick]} {return $u} 858 } 859 return "" 860 } 861 proc ::ts6::uid2nick {sck u} { 862 return [tnda get "nick/$::netname($sck)/$u"] 863 } 864 proc ::ts6::uid2rname {sck u} { 865 return [tnda get "rname/$::netname($sck)/$u"] 866 } 867 proc ::ts6::uid2rhost {sck u} { 868 return [tnda get "rhost/$::netname($sck)/$u"] 869 } 870 proc ::ts6::uid2host {sck u} { 871 return [tnda get "vhost/$::netname($sck)/$u"] 872 } 873 proc ::ts6::uid2ident {sck u} { 874 return [tnda get "ident/$::netname($sck)/$u"] 875 } 876 proc ::ts6::nick2host {sck nick} { 877 return [tnda get "vhost/$::netname($sck)/[nick2uid $netname $nick]"] 878 } 879 proc ::ts6::nick2ident {sck nick} { 880 return [tnda get "ident/$::netname($sck)/[nick2uid $netname $nick]"] 881 } 882 proc ::ts6::nick2rhost {sck nick} { 883 return [tnda get "rhost/$::netname($sck)/[nick2uid $netname $nick]"] 884 } 885 proc ::ts6::nick2ipaddr {sck nick} { 886 return [tnda get "ipaddr/$::netname($sck)/[nick2uid $netname $nick]"] 887 } 888 proc ::ts6::getts {sck chan} { 889 return [tnda get "channels/$::netname($sck)/[ndaenc $chan]/ts"] 890 } 891 proc ::ts6::getpfx {sck chan nick} { 892 return [tnda get "channels/$::netname($sck)/[ndaenc $chan]/status/[::ts6::nick2uid $netname $nick]"] 893 } 894 proc ::ts6::getupfx {sck chan u} { 895 return [tnda get "channels/$::netname($sck)/[ndaenc $chan]/status/$u"] 896 } 897 proc ::ts6::getpfxchars {sck modes} { 898 set o "" 899 foreach {c} [split $modes {}] { 900 append o [nda get "netinfo/$::netname($sck)/prefix/$c"] 901 } 902 return $o 903 } 904 proc ::ts6::getmetadata {sck nick metadatum} { 905 return [tnda get "metadata/$::netname($sck)/[::ts6::nick2uid $netname $nick]/[ndcenc $metadatum]"] 906 } 907 proc ::ts6::getcertfp {sck nick} { 908 return [tnda get "certfps/$::netname($sck)/[::ts6::nick2uid $netname $nick]"] 909 } 910 911 proc ::ts6::checkop {f t m p} { 912 set n [curctx net] 913 set mc [string index $m end] 914 #puts stdout [format ":%s MODE %s %s %s" $f $t $m $p] 915 putloglev d * "up $mc $f $t $p $n" 916 if {[tnda get "netinfo/$n/pfxchar/$mc"]==""} {::ts6::handlemode $f $t $m $p;return} 917 set chan [string map {/ [} [::base64::encode [string tolower $t]]] 918 tnda set "channels/$n/$chan/status/$p" [format {%s%s} [string map [list $mc ""] [tnda get "channels/$n/$chan/status/$p"]] $mc] 919 #puts stdout [format "Now, the state machine for $t looks like:"] 920 #puts stdout [tnda get "channels/$n/$chan"] 921 } 922 923 proc ::ts6::checkdeop {f t m p} { 924 set n [curctx net] 925 set mc [string index $m end] 926 # puts stdout [format ":%s MODE %s %s %s" $f $t $m $p] 927 putloglev d * "down $m ($mc) $f $t $p $n" 928 if {[tnda get "netinfo/$n/pfxchar/$mc"]==""} {::ts6::handlemode $f $t $m $p;return} 929 set chan [string map {/ [} [::base64::encode [string tolower $t]]] 930 if {[set thestatus [string map [list $mc ""] [tnda get "channels/$n/$chan/status/$p"]]] != ""} { 931 tnda set "channels/$n/$chan/status/$p" $thestatus 932 } else { 933 tnda unset "channels/$n/$chan/status/$p" 934 } 935 #puts stdout [format "Now, the state machine for $t looks like:"] 936 #puts stdout [tnda get "channels/$n/$chan"] 937 } 938 939 proc ::ts6::handlemode {from t mode parm} { 940 set n [curctx net] 941 set chan [string map {/ [} [::base64::encode [string tolower $t]]] 942 # puts stdout [format ":%s MODE %s %s %s" $from $t $mode $parm] 943 if {[string index $mode 0] == "+"} {set state 1} {set state 0} 944 set mc [string index $mode 1] 945 if {$state} { 946 if {[lsearch -exact [split [tnda get "netinfo/$n/chmban"] {}] $mc] == -1} {tnda set "channels/$n/$chan/mode" [format {%s%s} [string map [list $mc ""] [tnda get "channels/$n/$chan/mode"]] $mc]} 947 if {$parm != ""} { 948 if {[lsearch -exact [split [tnda get "netinfo/$n/chmban"] {}] $mc] != -1} { 949 set ban [tnda get "channels/$n/$chan/modes/[ndcenc $mc]"] 950 lappend ban $parm 951 tnda set "channels/$n/$chan/modes/[ndcenc $mc]" $ban 952 } { 953 tnda set "channels/$n/$chan/modes/[ndcenc $mc]" $parm 954 } 955 } 956 } { 957 if {[lsearch -exact [split [tnda get "netinfo/$n/chmban"] {}] $mc] == -1} {tnda set "channels/$n/$chan/mode" [string map [list $mc ""] [tnda get "channels/$n/$chan/mode"]]} 958 if {$parm != "" || [lsearch -exact [split [tnda get "netinfo/$n/chmpartparm"] {}] $mc] != -1} { 959 if {[lsearch -exact [split [tnda get "netinfo/$n/chmban"] {}] $mc] != -1} { 960 set ban [tnda get "channels/$n/$chan/modes/[ndcenc $mc]"] 961 lappend ban $parm 962 tnda set "channels/$n/$chan/modes/[ndcenc $mc]" $ban 963 } { 964 if {$parm == ""} { 965 tnda unset "channels/$n/$chan/modes/[ndcenc $mc]" 966 } { 967 tnda set "channels/$n/$chan/modes/[ndcenc $mc]" $parm 968 } 969 } 970 } 971 } 972 } 973 974 proc ::ts6::putnow {sck intclient msg} { 975 if {$intclient != ""} { 976 set nick [% intclient2uid $intclient] 977 } { 978 set nick $sid($sck) 979 } 980 putl $sck [format ":%s %s" $nick $msg] 981 } 982 proc ::ts6::uid2intclient {sck u} { 983 return [tnda get "intclient/$::netname($sck)/$u"] 984 } 985 986 proc ::ts6::getfreeuid {sck} { 987 set work 1 988 set cns [list] 989 foreach {_ cnum} [tnda get "intclient/$::netname($sck)"] {lappend cns $cnum} 990 while {0!=$work} {set num [expr {[rand 30000]+10000}];if {[lsearch -exact $cns $num]==-1} {set work 0}} 991 return $num 992 } 993 994 namespace export * 995 namespace ensemble create 996 } 997 998 #ts6 login $::sock