tclserv

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 8b24bba16430df875e211b86648120f35410f0b3
parent 6756637209c65761e1b5b429be7d3a37984922ba
Author: jaffacake <jaffacake@ronsor.(none)>
Date:   Mon, 25 Aug 2014 07:56:41 +0000

P10N gold standard - also a "syn" which does gateway cloaking now exists.

Diffstat:
M.gitignore | 2++
MLICENSE.md | 0
MREADME.md | 2+-
Mb64.tcl | 0
Mchanserv.conf.example | 0
Mchanserv.help | 0
Mcore/0000-conn.tcl | 0
Mcore/0002-p10.tcl | 2+-
Mcore/0003-ts6.tcl | 0
Acore/0004-p10n.tcl | 356+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcore/9999-protocol-common.tcl | 0
Adict.tcl | 630+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adnslib.php | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmain.tcl | 0
Rmodules/0001-eggcompat.tcl -> modules/0000-eggcompat.tcl | 0
Mmodules/0002-chanserv-thcserv.tcl | 0
Mmodules/0003-weather.tcl | 0
Mmodules/0004-limitserv.tcl | 0
Mmodules/0007-quote.tcl | 0
Mmodules/0008-relayserv.tcl | 0
Amodules/0009-gateway.tcl | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmodules/bmotion.disabled | 0
Rmodules/0005-chanserv.tcl -> modules/disabled.chanserv | 0
Mmodules/trigserv.disabled | 0
Mnda.tcl | 0
Mservices.conf.example | 0
26 files changed, 1115 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -2,3 +2,5 @@ *.db *.pem scripts/ +*.motd + diff --git a/LICENSE.md b/LICENSE.md diff --git a/README.md b/README.md @@ -1,3 +1,3 @@ read the code, i'm too lazy to document this shite. -one of the available scripts is a highly modified bmotion for tclserv. use at your own risk. +you need php. no questions. you need php. you also need tcl, obviously. but you need php. diff --git a/b64.tcl b/b64.tcl diff --git a/chanserv.conf.example b/chanserv.conf.example diff --git a/chanserv.help b/chanserv.help diff --git a/core/0000-conn.tcl b/core/0000-conn.tcl diff --git a/core/0002-p10.tcl b/core/0002-p10.tcl @@ -1,6 +1,6 @@ namespace eval p10 { -set sid [string repeat "A" [expr {2-[b64e $::numeric]}]] +set sid [string repeat "A" [expr {2-[string length [b64e $::numeric]]}]] append sid [b64e $::numeric] proc ::p10::sendUid {sck nick ident host dhost uid {realname "* Unknown *"} {modes "+oik"} {server ""}} { diff --git a/core/0003-ts6.tcl b/core/0003-ts6.tcl diff --git a/core/0004-p10n.tcl b/core/0004-p10n.tcl @@ -0,0 +1,356 @@ + +namespace eval p10n { +set sid [string repeat "A" [expr {2-[string length [b64e $::numeric]]}]] +append sid [b64e $::numeric] + +proc ::p10n::sendUid {sck nick ident host dhost uid {realname "* Unknown *"} {modes "+oik"} {server ""}} { + if {""==$server} {set server $::numeric} + set sid [string repeat "A" [expr {2-[string length [b64e $server]]}]] + append sid [b64e $server] + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + set sl [format "%s N %s 1 %s %s %s %s AAAAAA %s%s :%s" $sid $nick [clock format [clock seconds] -format %s] $ident $host $modes $sid $sendnn $realname] + tnda set "intclient/$::netname($sck)/${sid}${sendnn}" $uid + puts $sck $sl +} + +proc ::p10n::sendSid {sck sname sid {realname "In use by Services"}} { + set sl [format "%s S %s 2 %s %s P10 %s]]] 0 :%s" [b64e $::sid] $sname [clock format [clock seconds] -format %s] [clock format [clock seconds] -format %s] [b64e $sid] $realname] + puts $sck $sl +} + +proc ::p10n::topic {sck uid targ topic} { + set sid [string repeat "A" [expr {2-[string length [b64e $::numeric]]}]] + append sid [b64e $::numeric] + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + puts $sck [format "%s%s T %s :%s" $sid $sendnn $targ $topic] +} + +proc ::p10n::privmsg {sck uid targ msg} { + global sid + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + puts $sck [format "%s%s P %s :%s" $sid $sendnn $targ $msg] +} + +proc ::p10n::kick {sck uid targ tn msg} { + global sid + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + puts $sck [format "%s%s K %s %s :%s" $sid $sendnn $targ $tn $msg] +} + +proc ::p10n::kill {sck uid tn msg} { + global sid + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + puts $sck [format "%s%s D %s :%s" $sid $sendnn $tn $msg] +} + +proc ::p10n::notice {sck uid targ msg} { + global sid + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + puts $sck [format "%s%s O %s :%s" $sid $sendnn $targ $msg] +} + +proc ::p10n::setacct {sck targ msg} { + global sid + puts $sck [format "%s AC %s R %s" $sid $targ $msg] + tnda set "login/$::netname($sck)/$targ" $msg +} + +proc ::p10n::putwallop {sck msg} { + global sid + puts $sck [format "%s WA :%s" $sid $msg] +} + +proc ::p10n::sethost {sck uid targ msg} { + global sid + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + puts $sck [format "%s%s SH %s %s %s" $sid $sendnn $targ [tnda get "ident/$::netname($sck)/$targ"] $msg] + puts $sck [format "%s FA %s %s" $sid $targ $msg] + puts stdout [format "%s SH %s %s %s" $sid $targ [tnda get "ident/$::netname($sck)/$targ"] $msg] + tnda set "vhost/$::netname($sck)/$targ" $msg +} + +proc ::p10n::bind {sock type client comd script} { + set moretodo 1 + while {0!=$moretodo} { + set bindnum [rand 1 10000000] + if {[tnda get "binds/$sock/$type/$client/$comd/$bindnum"]!=""} {} {set moretodo 0} + } + tnda set "binds/$sock/$type/$client/$comd/$bindnum" $script + puts stdout "binds/$sock/$type/$client/$comd/$bindnum [tnda get "binds/$sock/$type/$client/$comd"]" + return $bindnum +} + +proc ::p10n::unbind {sock type client comd id} { + tnda set "binds/$sock/$type/$client/$comd/$id" "" +} + +proc ::p10n::putmode {sck uid targ mode parm ts} { + global sid + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + puts $sck [format "%s%s M %s %s %s" $sid $sendnn $targ $mode $parm $ts] +} + +proc ::p10n::putmotd {sck targ line} { + global sid + puts $sck [format "%s 372 %s :- %s" $sid $targ $line] +} + +proc ::p10n::mark {sck targ type line} { + global sid + puts $sck [format "%s MK %s %s :%s" $sid $targ $type $line] + puts stdout [format "%s MK %s %s :%s" $sid $targ $type $line] +} + +proc ::p10n::putmotdend {sck targ} { + global sid + puts $sck [format "%s 376 %s :End of global MOTD." $sid $targ] +} + +proc ::p10n::putjoin {sck uid targ ts} { + global sid + set sendid [b64e $uid] + set sendnn [string repeat "A" [expr {3-[string length $sendid]}]] + append sendnn $sendid + puts $sck [format "%s B %s %s %s%s:o" $sid $targ $ts $sid $sendnn] + puts stdout [format "%s B %s %s %s%s:o" $sid $targ $ts $sid $sendnn] + +} + +proc ::p10n::callbind {sock type client comd args} { + puts stdout "[tnda get "binds/$sock/$type/$client/$comd"]" + if {""!=[tnda get "binds/$sock/$type/$client/$comd"]} { + foreach {id script} [tnda get "binds/$sock/$type/$client/$comd"] { + $script [lindex $args 0] [lrange $args 1 end] + };return + } + #if {""!=[tnda get "binds/$type/-/$comd"]} {foreach {id script} [tnda get "binds/$type/-/$comd"] {$script [lindex $args 0] [lrange $args 1 end]};return} +} + +proc ::p10n::irc-main {sck} { + global sid sock + if {[eof $sck]} {puts stderr "duckfuck.";exit} + gets $sck line + set line [string trim $line "\r\n"] + set gotsplitwhere [string first " :" $line] + if {$gotsplitwhere==-1} {set comd [split $line " "]} {set comd [split [string range $line 0 [expr {$gotsplitwhere - 1}]] " "]} + set payload [split [string range $line [expr {$gotsplitwhere + 2}] end] " "] + switch -nocase -- [lindex $comd 1] { + "P" { + if {[string index [lindex $comd 2] 0] == "#"} { + set client chan + callbind $sck pub "-" [string tolower [lindex $payload 0]] [lindex $comd 2] [lindex $comd 0] [lrange $payload 1 end] p10 + callbind $sck evnt "-" "chanmsg" [lindex $comd 0] [lindex $comd 2] [lrange $payload 0 end] p10 + } { + set client [tnda get "intclient/$::netname($sck)/[lindex $comd 2]"] + callbind $sck msg $client [string tolower [lindex $payload 0]] [lindex $comd 0] [lrange $payload 1 end] p10 + callbind $sck "evnt" "-" "privmsg" [lindex $comd 0] [lindex $comd 2] [lrange $payload 0 end] p10 + } + } + + "O" { + if {[string index [lindex $comd 2] 0] == "#"} { + set client chan + callbind $sck pubnotc "-" [string tolower [lindex $payload 0]] [lindex $comd 2] [lindex $comd 0] [lrange $payload 1 end] p10 + callbind $sck pubnotc-m "-" [string tolower [lindex $payload 0]] [lindex $comd 2] [lindex $comd 0] [lrange $payload 1 end] p10 + callbind $sck "evnt" "-" "channotc" [lindex $comd 0] [lindex $comd 2] [lrange $payload 0 end] p10 + } { + set client [tnda get "intclient/$::netname($sck)/[lindex $comd 2]"] + callbind $sck notc $client [string tolower [lindex $payload 0]] [lindex $comd 0] [lrange $payload 1 end] + callbind $sck "evnt" "-" "privnotc" [lindex $comd 0] [lindex $comd 2] [lrange $payload 0 end] p10 + } + } + + "M" { + puts stdout [join [list {*}$comd {*}$payload] " "] + if {[string index [lindex $comd 2] 0] != "#"} {if {[lindex $comd 2] == [tnda get "nick/$::netname($sck)/[lindex $comd 0]"]} { + foreach {c} [split [lindex $comd 3] {}] { + switch -- $c { + "+" {set state 1} + "-" {set state 0} + "o" {tnda set "oper/$::netname($sck)/[lindex $comd 0]" $state} + } + } + } } { + set ctr 3 + foreach {c} [split [lindex $comd 3] {}] { + switch -regexp -- $c { + "\\\+" {set state 1} + "-" {set state 0} + "[aCcDdiMmNnOpQRrSsTtZz]" {callbind $sck mode "-" [expr {$state ? "+" : "-"}] $c [lindex $comd 0] [lindex $comd 2] $::netname($sck)} + "[belLkohv]" {callbind $sck mode "-" [expr {$state ? "+" : "-"}] $c [lindex $comd 0] [lindex $comd 2] [lindex $comd [incr ctr]] $::netname($sck)} + } + } + } + } + + "C" { + callbind $sck create "-" "-" [lindex $comd 2] [lindex $comd 0] $::netname($sck) + callbind $sck join "-" "-" [lindex $comd 2] [lindex $comd 0] $::netname($sck) + set chan [string map {/ [} [::base64::encode [string tolower [lindex $comd 2]]]] + tnda set "channels/$::netname($sck)/$chan/$::netname($sck)/ts" [lindex $comd 3] + } + + "T" { + callbind $sck topic "-" "-" [lindex $comd 2] [join $payload " "] + } + + "OM" { + set ctr 3 + foreach {c} [split [lindex $comd 3] {}] { + switch -regexp -- $c { + "\\\+" {set state 1} + "\\\-" {set state 0} + "[aCcDdiMmNnOpQRrSsTtZz]" {callbind $sck mode "-" [expr {$state ? "+" : "-"}] $c [lindex $comd 0] [lindex $comd 2]} + "[belLkohv]" {callbind $sck mode "-" [expr {$state ? "+" : "-"}] $c [lindex $comd 0] [lindex $comd 2] [lindex $comd [incr ctr]]} + } + } + } + + "B" { + set chan [string map {/ [} [::base64::encode [string tolower [lindex $comd 2]]]] + puts stdout "$chan" + if {[string index [lindex $comd 4] 0] == "+"} { + set four 5 + if {[string match "*l*" [lindex $comd 4]]} {incr four} + if {[string match "*L*" [lindex $comd 4]]} {incr four} + if {[string match "*k*" [lindex $comd 4]]} {incr four} + } { + set four 4 + } + tnda set "channels/$::netname($sck)/$chan/$::netname($sck)/ts" [lindex $comd 3] + foreach {nick} [split [lindex $comd $four] ","] { + set n [split $nick ":"] + set un [lindex $n 0] + set uo [lindex $n 1] + if {""!=$uo} {tnda set "channels/$::netname($sck)/$chan/modes/$::netname($sck)/$un" $uo} + callbind $sck join "-" "-" [lindex $comd 2] $un + } + + } + + "J" { + callbind $sck join "-" "-" [lindex $comd 2] [lindex $comd 0] + } + + "MO" { + callbind $sck motd "-" "-" [lindex $comd 0] + } + + "L" { + callbind $sck part "-" "-" [lindex $comd 2] [lindex $comd 0] + } + + "AC" { + tnda set "login/$::netname($sck)/[lindex $comd 2]" [lindex $comd 3] + callbind $sck account "-" "-" [lindex $comd 2] [lindex $comd 3] + } + + "K" { + callbind $sck part "-" "-" [lindex $comd 2] [lindex $comd 3] + } + + "EB" { + puts $sck "$sid EA" + } + + "N" { + if {[llength $comd] >= 5} { + set num 8 + set ctr 1 + set oper 0 + set loggedin "" + set fakehost "" + set modes "" + if {[string index [lindex $comd 7] 0] == "+"} {set modes [string range [lindex $comd 7] 1 end]; incr num} + foreach {c} [split $modes {}] { + puts stdout "$ctr $comd" + switch -exact -- $c { + "o" {set oper 1} + "r" {incr ctr;incr num; set loggedin [lindex $comd [expr {$ctr+6}]]} + "C" {incr ctr;incr num; set fakehost [lindex $comd [expr {$ctr+6}]]} + "c" {incr ctr;incr num; set fakehost [lindex $comd [expr {$ctr+6}]]} + "f" {incr ctr;incr num; set fakehost [lindex $comd [expr {$ctr+6}]]} + "h" {incr ctr;incr num; set fakehost [lindex [split [lindex $comd [expr {$ctr+7}]] "@"] 1]} + } + } + + if {""!=$loggedin} { + tnda set "login/$::netname($sck)/[lindex $comd $num]" $loggedin + } + + if {""!=$fakehost} { + tnda set "vhost/$::netname($sck)/[lindex $comd $num]" $fakehost + } + + tnda set "nick/$::netname($sck)/[lindex $comd $num]" [lindex $comd 2] + tnda set "oper/$::netname($sck)/[lindex $comd $num]" $oper + tnda set "ident/$::netname($sck)/[lindex $comd $num]" [lindex $comd 5] + tnda set "rhost/$::netname($sck)/[lindex $comd $num]" [lindex $comd 6] + callbind $sck conn "-" "-" [lindex $comd $num] + } { + callbind $sck nch "-" "-" [lindex $comd 0] [tnda get "nick/$::netname($sck)/[lindex $comd 0]"] [lindex $comd 2] + tnda set "nick/$::netname($sck)/[lindex $comd 0]" [lindex $comd 2] + } + } + + "Q" { + tnda set "login/$::netname($sck)/[lindex $comd 0]" "" + tnda set "nick/$::netname($sck)/[lindex $comd 0]" "" + tnda set "oper/$::netname($sck)/[lindex $comd 0]" 0 + tnda set "ident/$::netname($sck)/[lindex $comd 0]" "" + tnda set "rhost/$::netname($sck)/[lindex $comd 0]" "" + tnda set "vhost/$::netname($sck)/[lindex $comd 0]" "" + } + + "D" { + tnda set "login/$::netname($sck)/[lindex $comd 2]" "" + tnda set "nick/$::netname($sck)/[lindex $comd 2]" "" + tnda set "oper/$::netname($sck)/[lindex $comd 2]" 0 + tnda set "ident/$::netname($sck)/[lindex $comd 2]" "" + tnda set "rhost/$::netname($sck)/[lindex $comd 2]" "" + tnda set "vhost/$::netname($sck)/[lindex $comd 2]" "" + } + + "G" { + puts $sck "$sid Z [lindex $comd 3] [lindex $comd 2] [lindex $comd 4]" + } + } +} + +proc ::p10n::login {sck} { + global servername sid password + tnda set "pfx/owner" o + tnda set "pfx/protect" o + tnda set "pfx/halfop" h + set sid [string repeat "A" [expr {2-[string length [b64e $::numeric]]}]] + append sid [b64e $::numeric] + puts $sck "PASS :$password" + puts $sck "SERVER $servername 1 [clock format [clock seconds] -format %s] [clock format [clock seconds] -format %s] J10 $sid\]\]\] +s6h :Services for IRC Networks ($::netname($sck))" + puts $sck "$sid EB" + puts stdout "PASS :$password" + puts stdout "SERVER $servername 1 [clock format [clock seconds] -format %s] [clock format [clock seconds] -format %s] J10 $sid\]\]\] 0 :Services for IRC Networks" +} + + +#source services.conf +namespace export * +namespace ensemble create +} + +#p10 login $::sock diff --git a/core/9999-protocol-common.tcl b/core/9999-protocol-common.tcl diff --git a/dict.tcl b/dict.tcl @@ -0,0 +1,630 @@ +# dict.tcl +# http://wiki.tcl.tk/10609 +# +# Tcl 8.4-compatible implementation of the [dict] command. +# +# Known deficiencies: +# - In error messages, the variable name doesn't always appear correctly. This +# is due to use of [upvar] which renames the variable. +# - Tcl 8.4 offers no way for [return], [break], etc. inside the script to +# affect the caller. [uplevel] doesn't quite do everything that's needed. +# - Some usage error messages show different names for formal arguments. +# - Performance is reduced. +# +# Test failures (prefix each name with "dict-"): +# 3.12 4.5 5.7 9.7 9.8 11.15 12.7 12.8 12.10 +# 13.7 13.8 13.9 14.1 14.2 14.3 14.4 14.12 14.13 +# 14.22 15.9 15.10 15.11 16.8 16.9 16.17 16.18 17.13 +# 17.16 17.18 21.1 21.2 21.3 21.4 21.13 21.14 21.15 +# 22.1 22.2 22.3 22.10 22.14 22.15 23.1 23.2 24.1 +# 24.2 24.3 24.4 24.12 24.13 24.20.1 24.21 24.24 24.25 + +# Only create [dict] command if it doesn't already exist. +if {[catch {dict get {}}]} { + # Tcl 8.4-style implementation of namespace ensembles. + namespace eval ::dict {} + proc ::dict {subcommand args} { + # Confirm $subcommand is a [dict] command or unambiguous prefix thereof. + if {[regexp {[][*?\\]} $subcommand] + || [llength [set command [info commands ::dict::$subcommand*]]] != 1} { + set commands [string map {::dict:: {}}\ + [lsort [info commands ::dict::*]]] + if {[llength $commands] > 1} { + lset commands end "or [lindex $commands end]" + } + if {[llength $commands] > 2} { + set commands [join $commands ", "] + } else { + set commands [join $commands " "] + } + error "unknown or ambiguous subcommand \"$subcommand\":\ + must be $commands" + } + + # Invoke the command. + if {[catch {uplevel 1 [concat [list $command] $args]} msg]} { + # Rewrite the command name on error. + regsub {^(wrong # args: should be \")::(dict)::} $msg {\1\2 } msg + error $msg + } else { + return $msg + } + } + + # [dict append] + proc ::dict::append {varName key args} { + upvar 1 $varName var + + # Locate the matching key. On match, append to the key's value. + if {[::info exists var]} { + ::set var [get $var] + ::for {::set i 0} {$i < [llength $var]} {::incr i 2} { + if {[lindex $var $i] eq $key} { + ::incr i + return [lset var $i [lindex $var $i][join $args {}]] + } + } + } + + # On search failure, add the key to the dict. This code also will + # create the dict if it doesn't already exist. + ::lappend var $key [join $args {}] + } + + # [dict create] + proc ::dict::create {args} { + if {[llength $args] & 1} { + error "wrong # args: should be \"dict create ?key value ...?\"" + } + get $args + } + + # [dict exists] + proc ::dict::exists {dictionary key args} { + # Traverse through nested dicts searching for matches. + ::set sub $dictionary + foreach key [concat [list $key] $args] { + if {[llength $sub] & 1} { + return 0 + } + ::set match 0 + foreach {subkey sub} $sub { + if {$subkey eq $key} { + ::set match 1 + break + } + } + if {!$match} { + return 0 + } + } + return $match + } + + # [dict filter] + proc ::dict::filter {dictionary filterType args} { + # Invoke the correct filter handler. + ::set result {} + switch $filterType { + k - ke - key { + # Filter on keys. + foreach {key val} [get $dictionary] { + foreach pattern $args { + if {[string match $pattern $key]} { + ::lappend result $key $val + break + } + } + } + } v - va - val - valu - value { + # Filter on values. + foreach {key val} [get $dictionary] { + foreach pattern $args { + if {[string match $pattern $val]} { + ::lappend result $key $val + break + } + } + } + } s - sc - scr - scri - scrip - script { + # Filter on script returning true. + if {[llength $args] != 2} { + error "wrong # args: should be \"dict filter dictionary script\ + {keyVarName valueVarName} filterScript\"" + } elseif {[llength [lindex $args 0]] != 2} { + error "must have exactly two variable names" + } + upvar 1 [lindex $args 0 0] key [lindex $args 0 1] val + foreach {key val} [get $dictionary] { + if {[uplevel 1 [lindex $args 1]]} { + ::lappend result $key $val + } + } + } default { + error "bad filterType \"$filterType\":\ + must be key, script, or value" + }} + return $result + } + + # [dict for] + proc ::dict::for {keyVarValueVar dictionary script} { + if {[llength $keyVarValueVar] != 2} { + error "must have exactly two variable names" + } + + # [foreach] does what's needed, mostly. Tcl 8.4 offers no way for + # [return], etc. inside the script to make the caller return. + uplevel 1 [list foreach $keyVarValueVar [get $dictionary] $script] + } + + # [dict get] + proc ::dict::get {dictionary args} { + if {[llength $args]} { + # When given multiple arguments, traverse nested dicts to find the + # requested key. Fail if the key is not found. + ::set sub $dictionary + foreach key $args { + if {[llength $sub] & 1} { + error "missing value to go with key" + } + ::for {::set i [expr {[llength $sub] - 2}]} {1} {::incr i -2} { + if {$i < 0} { + error "key \"$key\" not known in dictionary" + } elseif {[lindex $sub $i] eq $key} { + break + } + } + ::set sub [lindex $sub [expr {$i + 1}]] + } + return $sub + } else { + # With only one argument, convert that argument to a canonical dict. + if {[llength $dictionary] & 1} { + error "missing value to go with key" + } + ::for {::set i 0} {$i < [llength $dictionary]} {::incr i 2} { + if {[::info exists indexes([lindex $dictionary $i])]} { + lset dictionary $indexes([lindex $dictionary $i])\ + [lindex $dictionary [expr {$i + 1}]] + ::set dictionary [lreplace $dictionary $i [expr {$i + 1}]] + ::incr i -2 + } else { + ::set indexes([lindex $dictionary $i]) [expr {$i + 1}] + } + } + return $dictionary + } + } + + # [dict incr] + proc ::dict::incr {varName key {increment 1}} { + upvar 1 $varName var + + # Disallow non-integer increments. + if {![string is integer -strict $increment]} { + error "expected integer but got \"$increment\"" + } + + # Locate the matching key and increment its value. + if {[::info exists var]} { + ::set var [get $var] + ::for {::set i 0} {$i < [llength $var]} {::incr i 2} { + if {$key eq [lindex $var $i]} { + ::incr i + + # Disallow non-integer values. + if {![string is integer -strict [lindex $var $i]]} { + error "expected integer but got \"[lindex $var $i]\"" + } + + # Increment the value in place. + return [lset var $i [expr {[lindex $var $i] + $increment}]] + } + } + } + + # On search failure, add the key to the dict. This code also will + # create the dict if it doesn't already exist. + ::lappend var $key $increment + } + + # [dict info] + proc ::dict::info {dictionary} { + # Make sure the dictionary is valid. + if {[llength $dictionary] & 1} { + error "missing value to go with key" + } + + # No hash table. + return "dict is represented as plain list" + } + + # [dict keys] + proc ::dict::keys {dictionary {pattern *}} { + # Build and return a list of matching keys. + ::set result {} + foreach {key val} [get $dictionary] { + if {[string match $pattern $key]} { + ::lappend result $key + } + } + return $result + } + + # [dict lappend] + proc ::dict::lappend {varName key args} { + upvar 1 $varName var + + # Locate the matching key and append a list element to its value. + if {[::info exists var]} { + ::set var [get $var] + ::for {::set i 0} {$i < [llength $var]} {::incr i 2} { + if {$key eq [lindex $var $i]} { + ::incr i + + # Disallow non-list values. + llength [lindex $var $i] + + # Increment the value in place. + return [lset var $i [concat [lindex $var $i] $args]] + } + } + } + + # On search failure, add the key to the dict. This code also will + # create the dict if it doesn't already exist. + ::lappend var $key $args + } + + # [dict map] + proc ::dict::map {keyVarValueVar dictionary script} { + # Confirm argument syntax. + if {[llength $keyVarValueVar] != 2} { + error "must have exactly two variable names" + } + + # Link to local variables which will be used as iterators. + upvar 1 [lindex $keyVarValueVar 0] key [lindex $keyVarValueVar 1] val + + # Accumulate and return the result. + ::set result {} + foreach {key val} [get $dictionary] { + ::lappend result $key [uplevel 1 $script] + } + return $result + } + + # [dict merge] + proc ::dict::merge {args} { + # Confirm each argument is a dict. + foreach dict $args { + if {[llength $dict] & 1} { + error "missing value to go with key" + } + } + + # Merge the dicts, then normalize. + get [eval [list concat] $args] + } + + # [dict remove] + proc ::dict::remove {dictionary args} { + # Remove all dictionary keys matching any of the key arguments. + ::set dictionary [get $dictionary] + ::set args [lsort -unique $args] + ::for {::set i 0} {$i < [llength $dictionary]} {::incr i 2} { + ::set index [lsearch -exact -sorted $args [lindex $dictionary $i]] + if {$index >= 0} { + ::set dictionary [lreplace $dictionary $i [expr {$i + 1}]] + ::set args [lreplace $args $index $index] + if {![llength $args]} { + break + } + ::incr i -2 + } + } + return $dictionary + } + + # [dict replace] + proc ::dict::replace {dictionary args} { + # Confirm correct argument parity. + if {[llength $args] & 1} { + error "wrong # args:\ + should be \"dict replace dictionary ?key value ...?\"" + } + + # Concatenate the dicts then use [get] to canonicalize the result. + get [eval [list concat $dictionary] $args] + } + + # [dict set] + proc ::dict::set {varName key args} { + upvar 1 $varName var + + # Confirm that a value argument was given. + if {![llength $args]} { + error "wrong # args:\ + should be \"dict set varName key ?key ...? value\"" + } + + # Default the dictionary to empty. + if {![::info exists var]} { + ::set var {} + } + + # Shuffle the arguments into the right variables. + ::set keys [concat [list $key] [lrange $args 0 end-1]] + ::set val [lindex $args end] + + # Traverse through nested dicts to find the key to insert or replace. + ::set path {} + ::set sub $var + ::for {::set i 0} {$i < [llength $keys]} {::incr i} { + # Canonicalize each level of nested dicts. + lset var $path [::set sub [get $sub]] + + # Search the current level to see if any keys match. + ::for {::set j 0} {1} {::incr j 2} { + if {$j >= [llength $sub]} { + # On match failure, move the remaining keys into the value, + # transforming it into a nested dict, then set that value. + ::set j [expr {[llength $keys] - 1}] + ::for {} {$j > $i} {::incr j -1} { + ::set val [list [lindex $keys $j] $val] + } + lset var $path [concat $sub [list [lindex $keys $i] $val]] + return $var + } elseif {[lindex $sub $j] eq [lindex $keys $i]} { + # On match success, advance to the next level of nesting. + break + } + } + + # Descend into the value associated with the matching key. + ::incr j + ::lappend path $j + ::set sub [lindex $sub $j] + } + + # Replace the value of the matched key. + lset var $path $val + } + + # [dict size] + proc ::dict::size {dictionary} { + # Canonicalize the dict and return half its length. + expr {[llength [get $dictionary]] / 2} + } + + # [dict unset] + proc ::dict::unset {varName key args} { + upvar 1 $varName var + + # Handle the case of the dict not existing. + if {![::info exists var]} { + if {[llength $args]} { + # Fail when unsetting a nested key. + error "key \"$key\" not known in dictionary" + } else { + # Create the dict when unsetting a non-nested key. + ::set var {} + return + } + } + + # Traverse through nested dicts to find the key to remove. + ::set keys [concat [list $key] $args] + ::set path {} + ::set sub $var + ::for {::set i 0} {1} {::incr i} { + # Canonicalize each level of nested dicts. + lset var $path [::set sub [get $sub]] + + # Search the current level to see if any keys match. + ::for {::set j 0} {$j < [llength $sub]} {::incr j 2} { + if {[lindex $sub $j] eq [lindex $keys $i]} { + break + } + } + + # Handle outer and innermost nesting levels differently. + if {$i < [llength $keys] - 1} { + # In parent levels, search failure is an error. + if {$j >= [llength $sub]} { + error "key \"[lindex $keys $i]\" not known in dictionary" + } + + # Descend into the value associated with the matching key. + ::incr j + ::lappend path $j + ::set sub [lindex $sub $j] + } else { + # In the innermost level, search failure is acceptable. On + # search success, remove the key, otherwise just ignore. + if {$j < [llength $sub]} { + lset var $path [lreplace $sub $j [expr {$j + 1}]] + } + + # Return the updated dictionary. + return $var + } + } + } + + # [dict update] + proc ::dict::update {varName key valVarName args} { + # Confirm argument parity. + if {!([llength $args] & 1)} { + error "wrong # args: should be \"dict update varName key valVarName\ + ?key valVarName ...? script\"" + } + ::set script [lindex $args end] + + # Convert the list of keys and variable names to an array. + array set names [concat [list $key $valVarName] [lrange $args 0 end-1]] + + # Copy the dict values into the caller's variables. + upvar 1 $varName dict + foreach {key val} [get $dict] { + if {[::info exists names($key)]} { + upvar 1 $names($key) valVar + ::set valVar $val + } + } + + # Invoke the caller-supplied script. + ::set result [uplevel 1 $script] + + # If the dict is gone, let it stay gone. Otherwise update it. + if {[::info exists dict]} { + # Update the dict values from the caller's variables, and remove + # keys corresponding to unset variables. + ::for {::set i 0} {$i < [llength $dict]} {::incr i 2} { + if {[::info exists names([lindex $dict $i])]} { + upvar 1 $names([lindex $dict $i]) valVar + ::unset names([lindex $dict $i]) + if {[::info exists valVar]} { + lset dict [expr {$i + 1}] $valVar + } else { + ::set dict [lreplace $dict $i [expr {$i + 1}]] + ::incr i -2 + } + } + } + + # Add keys back to the dict from the caller's variables, in case the + # caller removed some keys directly from the dict. + foreach {key valVarName} [array get names] { + upvar 1 $valVarName valVar + if {[::info exists valVar]} { + ::lappend dict $key $valVar + } + } + } + + # Return the result of the script. + return $result + } + + # [dict values] + proc ::dict::values {dictionary {pattern *}} { + # Build and return a list of matching values. + ::set result {} + foreach {key val} [get $dictionary] { + if {[string match $pattern $val]} { + ::lappend result $val + } + } + return $result + } + + # [dict with] + proc ::dict::with {varName args} { + upvar 1 $varName dict + + # Confirm a script argument was supplied. + if {![llength $args]} { + error "wrong # args:\ + should be \"dict with varName ?key ...? script\"" + } + ::set script [lindex $args end] + ::set args [lrange $args 0 end-1] + + # Traverse through nested dicts to find the dict on which to operate. + ::set path {} + ::set sub [get $dict] + foreach key $args { + # Canonicalize each level of nested dicts. + lset dict $path $sub + + # Search the current level to see if any keys match. + ::for {::set i 0} {$i < [llength $sub]} {::incr i 2} { + if {[lindex $sub $i] eq $key} { + break + } + } + + # Terminate on match failure. + if {$i >= [llength $sub]} { + error "key \"$key\" not known in dictionary" + } + + # Descend into the value associated with the matching key. + ::incr i + ::set sub [get [lindex $sub $i]] + ::lappend path $i + } + + # Copy the dict values into the caller's variables. Make an array to + # keep track of all the keys in the dict. + foreach {key val} $sub { + upvar 1 $key valVar + ::set valVar $val + ::set keys($key) {} + } + + # Invoke the caller-supplied script. + ::set result [uplevel 1 $script] + + # If the dict is gone, let it stay gone. Otherwise update it. + if {[::info exists dict]} { + # Traverse through nested dicts again in case the caller-supplied + # script reorganized the dict. + ::set path {} + ::set sub [get $dict] + foreach key $args { + # Canonicalize each level of nested dicts. + lset dict $path $sub + + # Search the current level to see if any keys match. + ::for {::set i 0} {$i < [llength $sub]} {::incr i 2} { + if {[lindex $sub $i] eq $key} { + break + } + } + + # Terminate on match failure. + if {$i >= [llength $sub]} { + error "key \"$key\" not known in dictionary" + } + + # Descend into the value associated with the matching key. + ::incr i + ::set sub [get [lindex $sub $i]] + ::lappend path $i + } + + # Update the dict values from the caller's variables, and remove + # keys corresponding to unset variables. + ::for {::set i 0} {$i < [llength $sub]} {::incr i 2} { + if {[::info exists keys([lindex $sub $i])]} { + upvar 1 [lindex $sub $i] valVar + ::unset keys([lindex $sub $i]) + if {[::info exists valVar]} { + lset sub [expr {$i + 1}] $valVar + } else { + ::set sub [lreplace $sub $i [expr {$i + 1}]] + ::incr i -2 + } + } + } + + # Add keys back to the dict from the caller's variables, in case the + # caller removed some keys directly from the dict. + foreach key [array names keys] { + upvar 1 $key valVar + if {[::info exists valVar]} { + ::lappend sub $key $valVar + } + } + + # Save the updated nested dict back into the dict variable. + lset dict $path $sub + } + + # Return the result of the script. + return $result + } +} diff --git a/dnslib.php b/dnslib.php @@ -0,0 +1,54 @@ +<?php + +# Following function is jaffacake's own work. +# GPLv3 blablabla + +define("DNSBL",0x1); +define("NORMLOOKUP",0x2); +define("V6LOOKUP",0x4); +define("REVLOOKUP",0x8); + +function dig($name, $qtype, $dnsbl = ".", $isdnsbl = false) { + $type = 0; + if ($isdnsbl >= 1) { + $isipv6 = (strpos($name, ":") !== FALSE); + if ($dnsbl == ".") return false; + if ($isipv6) { + $type = $type | V6LOOKUP; + } + $type = $type | DNSBL; + $type = $type | REVLOOKUP; + } + if (!$isdnsbl) $type = NORMLOOKUP; + if ($qtype == "PTR") { + $isipv6 = (strpos($name, ":") !== FALSE); + if ($isipv6) { + $type = $type | REVLOOKUP; + } + $type = $type | REVLOOKUP; + } + if ($type & 0x8) { + if ($type & V6LOOKUP) $rdns = implode(".",str_split(strrev(implode("",explode(":",$name))))); + else $rdns = implode(".",array_reverse(explode(".",$name))); + $dname = $rdns; + if (($type & 0x4) and ($type & 0x1)) $dname .= ".ip6.arpa"; + else if ($type & 0x2) $dname .= ".in-addr.arpa"; + else { + $dname .= ".".$dnsbl; + } + } else $dname = $name; + $dnsname = "dig +short +time=1 ".escapeshellarg($dname)." ".escapeshellarg(strtoupper($qtype))." | tail -n 1"; + $out = shell_exec($dnsname); + if ($type & 0x1) { + $num = explode(".",$out); + $numreply = 0; + $numreply = $numreply + $num[3]; + $numreply = $numreply + ($num[2] << 8); + $numreply = $numreply + ($num[1] << 16); + // We'll return the pton result :P + return $numreply; + } + return $out; +} + +print($argv[5]. " " .dig($argv[1], $argv[2], $argv[3], $argv[4]). "\n"); diff --git a/main.tcl b/main.tcl diff --git a/modules/0001-eggcompat.tcl b/modules/0000-eggcompat.tcl diff --git a/modules/0002-chanserv-thcserv.tcl b/modules/0002-chanserv-thcserv.tcl diff --git a/modules/0003-weather.tcl b/modules/0003-weather.tcl diff --git a/modules/0004-limitserv.tcl b/modules/0004-limitserv.tcl diff --git a/modules/0007-quote.tcl b/modules/0007-quote.tcl diff --git a/modules/0008-relayserv.tcl b/modules/0008-relayserv.tcl diff --git a/modules/0009-gateway.tcl b/modules/0009-gateway.tcl @@ -0,0 +1,71 @@ +$::maintype sendUid $sock syn syn channels. channels. 1444 "Tin" +bind $::sock msg 1444 "addgwcloak" addgwcloak +bind $::sock msg 1444 "addaccloak" addaccloak +bind $::sock conn - - dogwcloak +bind $::sock motd - - dogwcloak +bind $::sock msg 1444 "motd" dogwcloak + +proc addgwcloak {from msg} { + set uname [tnda get "login/$::netname($::sock)/$from"] + if {$::synpass != [lindex $msg 0 2]} { + $::maintype notice $::sock 1444 $from "SYNTAX: /msg syn addgwcloak match cloak syn-password" + $::maintype notice $::sock 1444 $from "FORMATCHAR: %i = realhost" + return + } + if {""==[lindex $msg 0 0]} { + $::maintype notice $::sock 1444 $from "SYNTAX: /msg syn addgwcloak match cloak" + $::maintype notice $::sock 1444 $from "FORMATCHAR: %i = realhost" + return + + } + if {""==[lindex $msg 0 1]} { + $::maintype notice $::sock 1444 $from "SYNTAX: /msg syn addgwcloak match cloak" + $::maintype notice $::sock 1444 $from "FORMATCHAR: %i = realhost" + return + + } + nda set "gwcloaks/[lindex $msg 0 0]" [lindex $msg 0 1] +} + +proc dogwcloak {unick n} { + doinsecurehost $unick + set fp [open ./services.motd r] + set fl [read $fp] +# set fl "" + close $fp + foreach {l} [split $fl "\r\n"] { + $::maintype putmotd $::sock $unick "$l" + } + $::maintype putmotdend $::sock $unick + set match [tnda get "rhost/$::netname($::sock)/$unick"] + foreach {mask cloak} [nda get "gwcloaks"] { + if {[string match -nocase $mask "[tnda get "nick/$::netname($::sock)/$unick"]![tnda get "ident/$::netname($::sock)/$unick"]@[tnda get "rhost/$::netname($::sock)/$unick"]"]} {set match $cloak} + } + set cloake [string map [list "::" "-" ":" "."] [string map [list "%i" [tnda get "rhost/$::netname($::sock)/$unick"]] $match]] + $::maintype notice $::sock 1444 $unick "$cloake should be your vHost." + $::maintype sethost $::sock 1444 $unick "$cloake" + $::maintype putwallop $::sock "CONNECT: [tnda get "nick/$::netname($::sock)/$unick"]![tnda get "ident/$::netname($::sock)/$unick"]@[tnda get "rhost/$::netname($::sock)/$unick"] ($cloake)" +} + +proc doinsecurehost {unick} { + package require ip + set rhostname [tnda get "rhost/$::netname($::sock)/$unick"] + if {![string match "*:*" $rhostname] && [catch {::ip::toInteger $rhostname}]} { + if {![catch "exec php ./dnslib.php [string trim $rhostname] A . 0 $unick" reho]} {set rhostname [lindex [split [string trim $reho] " "] 1]} elseif {![catch "exec php ./dnslib.php [string trim $rhostname] AAAA . 0 $unick" reho]} {set rhostname [lindex [split [string trim $reho] " "] 1]} {puts stdout "gave up $rhostname $unick";return} + # If we returned then we gave up. + } + if {[string match "*:*" $rhostname]} {return;} + foreach {dnsbl} $::dnsbls { + set fp [open |[list php ./dnslib.php [string trim $rhostname] A $dnsbl 1 $unick] r] + set reho [read $fp] + catch "close $fp" + set reho [string trim $reho] + if {[lindex [split $reho " "] 0] == $unick} {set result [lindex [split $reho " "] 1]} {puts stdout "gave up $rhostname $unick results /$reho/";return} + # If we returned then we gave up. + if {$result!="" && $result != 0 && $result != 1} {$::maintype kill $::sock 1444 $unick "(DNSBL::$::dname($dnsbl) match - if this is in error contact j4jackj)"} + } +} + +set dname(dnsbl.dronebl.org) DroneBL +set dname(6667.141.117.162.69.ip-port.exitlist.torproject.org) Tor +set dnsbls [list dnsbl.dronebl.org 6667.141.117.162.69.ip-port.exitlist.torproject.org] diff --git a/modules/bmotion.disabled b/modules/bmotion.disabled diff --git a/modules/0005-chanserv.tcl b/modules/disabled.chanserv diff --git a/modules/trigserv.disabled b/modules/trigserv.disabled diff --git a/nda.tcl b/nda.tcl diff --git a/services.conf.example b/services.conf.example