
proc var_fserve:func:startup {} {
global var_fserve_slots
if {![info exists var_fserve_slots(pending)]} then {
set var_fserve_slots(pending) ""
}
var_fserve:func:stats-init
var_fserve:func:binds
var_fserve:func:pub-ad
var_fserve:func:du
var_fserve:func:genindex
var_fserve:func:traceinit
if {![string match *var?fserve?func?floodctrl* [string tolower [utimers]]]} then {
utimer 5 "var_fserve:func:floodctrl clean"
}
if {![string match *var?fserve?func?pendclean* [string tolower [utimers]]]} then {
utimer 15 var_fserve:func:pendclean
}
if {![string match *var?fserve?func?pendcheck* [string tolower [utimers]]]} then {
utimer 20 var_fserve:func:pendcheck
}
}
### VALID NUM CHECK ###
proc var_func:validnum {num} {
catch {
expr $num * 0
} result
if {$result != 0} then {
return 0
} else {
return 1
}
}
### mIRC CONTROL CHARS ###
proc b {} {
return
}
proc k {} {
return
}
proc o {} {
return
}
proc r {} {
return
}
proc u {} {
return
}
### SETTINGS VALIDATION ###
set ferr "Fserve error:"
set rerr "Error loading"
# Eggdrop version test
if {$numversion < 1032900} then {
putlog "Fserve warning: Eggdrop version must be at least 1.3.29 for the Fserve to work properly"
}
# Variable existance test
foreach setting {
var_fserve(enable)
var_fserve(ad_while_off)
var_fserve(validuser)
var_fserve(bind)
var_fserve(killonpart)
var_fserve(onjoin)
var_fserve(ad)
var_fserve(ad_delay)
var_fserve(ad_linemin)
var_fserve(mainpath)
var_fserve(statsref)
var_fserve(msg_to_notonchan)
var_fserve(maxmatches)
var_fserve(motd)
var_fserve(banfile)
var_fserve(jdirs)
var_fserve(allowjan)
var_fserve_floodratio
var_fserve(maxdloads)
var_fserve(maxqueue)
var_fserve(maxsends)
var_fserve(maxslots)
var_fserve(maxclone)
var_fserve(maxidle)
var_fserve(maxchars)
var_fserve(admode)
var_fserve(janflags)
} {
if {![info exists $setting] } then {
putlog "$ferr \$$setting variable was not set in configuration"
return $rerr
}
}
# Valid number test
foreach setting {
var_fserve(ad_delay)
} {
if {![var_func:validnum [subst $$setting]]} then {
putlog "$ferr \$$setting must be a valid number."
return $rerr
}
}
# Valid integer test
foreach setting {
var_fserve(ad_linemin)
var_fserve(maxdloads)
var_fserve(maxqueue)
var_fserve(maxsends)
var_fserve(maxslots)
var_fserve(maxclone)
var_fserve(maxidle)
var_fserve(maxchars)
var_fserve(statsref)
var_fserve(enable)
var_fserve(allowjan)
var_fserve(ad_while_off)
var_fserve(validuser)
var_fserve(killonpart)
var_fserve(onjoin)
var_fserve(ad)
var_fserve(msg_to_notonchan)
var_fserve(admode)
} {
if {![var_func:validnum [subst $$setting]] || int([subst $$setting]) != [subst $$setting]} then {
putlog "$ferr \$$setting must be a valid integer."
return $rerr
}
}
# Valid fserves paths test
catch {
set var_fserve_pwd [pwd]
set var_fserve_temp1 [catch {cd $var_fserve(mainpath)}]
set var_fserve_temp2 [catch {cd $var_fserve_pwd}]
}
if {$var_fserve_temp1 || $var_fserve_temp2} then {
putlog "$ferr cannot chdir to '$var_fserve(mainpath)'. Invalid main file server path."
return $rerr
}
catch {
foreach entry $var_fserve(sections) {
if {[lindex $entry 1] == ""} then {
set var_fserve_temp1 1
} else {
set var_fserve_pwd [pwd]
set var_fserve_tpath "$var_fserve(mainpath)/[lindex $entry 1]"
set var_fserve_temp1 [catch {cd $var_fserve_tpath}]
set var_fserve_temp2 [catch {cd $var_fserve_pwd}]
if {$var_fserve_temp1 || $var_fserve_temp2} then break
}
}
}
if {$var_fserve_temp1 || $var_fserve_temp2} then {
putlog "$ferr cannot chdir to '$var_fserve(mainpath)/[lindex $entry 1]'. Invalid path specified for '[lindex $entry 0]' file server."
return $rerr
}
# Valid maxidle time test
if {$var_fserve(maxidle) < 1} then {
putlog "$ferr \$var_fserve(maxidle) must be a valid integer greater than 0"
return $rerr
}
# Valid minport and maxport value test
if {$var_fserve(minport) && $var_fserve(maxport)} then {
if {$var_fserve(minport) < 1024 || $var_fserve(minport) > 65535} then {
putlog "$ferr \$var_fserve(minport) value is out of range (1024-65535)"
return $rerr
} elseif {$var_fserve(maxport) < 1024 || $var_fserve(maxport) > 65535} then {
putlog "$ferr \$var_fserve(maxport) value is out of range (1024-65535)"
return $rerr
} elseif {$var_fserve(minport) > $var_fserve(maxport)} then {
putlog "$ferr \$var_fserve(minport) can't be greater than \$var_fserve(maxport)"
return $rerr
} elseif {$var_fserve(minport) == $var_fserve(maxport)} then {
putlog "$ferr \$var_fserve(minport) can't be equal to \$var_fserve(maxport)"
return $rerr
}
} else {
set var_fserve(minport) 0
et var_fserve(maxport) 0
}
# MOTD file existance test
if {$var_fserve(motd) != "" && ![file exists $var_fserve(motd)]} then {
putlog "$ferr specified MOTD file ($var_fserve(motd)) doesn't exist."
return $rerr
}
# Bans file initialization/loading
if {$var_fserve(banfile) == "" } then {
putlog "$ferr no bans file specified."
return $rerr
} elseif {[file exists $var_fserve(banfile)]} {
foreach entry [lsort [array names var_fserve_bans]] {
unset var_fserve_bans($entry)
}
set fd [open $var_fserve(banfile) "r"]
set count 1
while {![eof $fd]} {
gets $fd ban
if {$ban != ""} then {
set var_fserve_bans($count) "$ban"
incr count
}
}
unset count
unset ban
close $fd
} else {
set fd [open $var_fserve(banfile) "w"]
close $fd
}
unset fd
unset setting
unset ferr
unset rerr
unset var_fserve_tpath
unset var_fserve_temp1
unset var_fserve_temp2
### VARIABLE TRACE INITIALIZATION ###
proc var_fserve:func:traceinit {} {
global var_fserve
foreach var {
var_fserve(triggers)
var_fserve(bind)
var_fserve(enable)
} {
var_func:tracedel $var
trace variable $var w var_func:tracecall
}
return
}
proc var_func:tracecall {var index mode} {
switch -- $var\
var_fserve {
switch -- $index\
triggers {
var_fserve:func:binds
} bind {
var_fserve:func:binds
} enable {
global var_fserve var_fserve_stats
set var_fserve_stats(reenable) [expr ($var_fserve_stats(reenable) == 2) ? 1 : 0]
if {!$var_fserve(enable) && $var_fserve_stats(wasenabled)} then {
putlog "Fserve: Disabled."
} elseif {$var_fserve(enable) && !$var_fserve_stats(wasenabled)} then {
putlog "Fserve: Enabled."
}
set var_fserve_stats(wasenabled) $var_fserve(enable)
} default {
return
}
} default {
return
}
}
proc var_func:tracedel {var} {
global var_fserve
foreach element [trace vinfo $var] {
uplevel 0 trace vdelete $var [lindex $element 0] [lindex $element 1]
}
return
}
### FREE SLOT COUNTER ###
proc var_fserve:func:slotcount {} {
global var_fserve var_fserve_availslots var_fserve_slots
set count [expr [array size var_fserve_slots] - 1 + [llength $var_fserve_slots(pending)]]
set var_fserve_availslots [expr ($count > $var_fserve(maxslots)) ? 0 : $var_fserve(maxslots) - $count]
return $var_fserve_availslots
}
proc var_fserve:func:sendscount {} {
global var_fserve
set sends 0
set output ""
foreach entry [dcclist GET] {
incr sends
}
foreach entry [dcclist GET_PENDING] {
incr sends
}
set sends [expr $var_fserve(maxsends) - $sends]
set output [linsert $output 0 $sends]
return $output
}
### AD GENERATOR ###
proc var_fserve:func:adgen {} {
global var_fserve var_fserve_stats var_fserve_queue
if {$var_fserve(enable)} then {
set enable ONLINE
} else {
set enable OFFLINE
}
if {[llength $var_fserve(triggers)] > 1} then {
set triggers "Triggers: "
} else {
set triggers "Trigger: "
}
set tcount 1
foreach trigger $var_fserve(triggers) {
if {$tcount > 1} then {
append triggers ", \02$trigger\02"
} else {
append triggers "\02$trigger\02"
}
incr tcount
}
set chatslots "\02[var_fserve:func:slotcount] of $var_fserve(maxslots)\02 chat slots available."
set sendslots "\02[var_fserve:func:sendscount] of $var_fserve(maxsends)\02 send slots available."
set offer "Currently offering \02[format %ld [expr $var_fserve_stats(koffered) / 1024]]\02 MB in \02[var_func:nformat $var_fserve_stats(foffered)]\02 files."
if {$var_fserve(maxqueue)} then {
set queueslots "\02[expr $var_fserve(maxqueue) - [array size var_fserve_queue]] of $var_fserve(maxqueue)\02 queue slots available."
return "\02$var_fserve(name)\02. $triggers. \003Status: $enable\003. $chatslots $sendslots $queueslots $offer"
} else {
return "\02$var_fserve(name)\02. $triggers. \003Status: $enable\003. $chatslots $sendslots $offer"
}
}
### MOTD DISPLAYER ###
proc var_fserve:func:motd {{idx ""}} {
global var_fserve var_fserve_slots
if {![info exists var_fserve_slots($idx)]} then {
return "Invalid idx"
}
set infile [open $var_fserve(motd)]
set temp [unixtime]![clock clicks]
while {![eof $infile]} {
gets $infile line
set line [split $line]
while {[set match [lsearch -glob $line %*]] != -1} {
set lmatch $match
switch -- [string range [lindex $line $match] 1 end]\
botnick {
global botnick
set replacement $botnick
} nick {
set replacement [var_fserve:func:slots get $idx nick]
} uhost {
set replacement [var_fserve:func:slots get $idx host]
} version {
set replacement $var_fserve(ver)
} serv {
set replacement $var_fserve(name)
} % {
set replacement ${temp}!percent
} freeslots {
set replacement [var_fserve:func:slotcount]
} totalslots {
set replacement $var_fserve(maxslots)
} usedslots {
set replacement [expr [llength [array names var_fserve_slots]] -1]
} time12 {
set replacement [strftime "%I:%M %p"]
} time24 {
set replacement [strftime "%H:%M"]
} date2 {
set replacement [strftime %m-%d-%y]
} date4 {
set replacement [strftime %m-%d-%Y]
} strdate {
set replacement [strftime "%B %d, %Y"]
} maxdl {
set replacement $var_fserve(maxdloads)
} maxgs {
set replacement $var_fserve(maxsends)
} queue {
if {$var_fserve(maxqueue)} then {
set replacement $var_fserve(maxqueue)
} else {
set replacement "Queue disabled"
}
} trigcount {
global var_fserve_stats
set replacement $var_fserve_stats(uses)
} filecount {
global var_fserve_stats
set replacement $var_fserve_stats(foffered)
} filecntf {
global var_fserve_stats
set replacement [var_func:nformat $var_fserve_stats(foffered)]
} kilocount {
global var_fserve_stats
set replacement $var_fserve_stats(koffered)
} kilocntf {
global var_fserve_stats
set replacement $var_fserve_stats(koffered)
} megcount {
global var_fserve_stats
set replacement [format %ld [expr $var_fserve_stats(koffered) / 1024]]
} megcntf {
global var_fserve_stats
set replacement [var_func:nformat [format %ld [expr $var_fserve_stats(koffered) / 1024]]]
} b {
set replacement ${temp}!backsp
} default {
set replacement ""
}
set line [lreplace $line $match $match $replacement]
}
while {[set match [lsearch $line ${temp}!percent]] != -1} {
set line [lreplace $line $match $match %]
}
set line [split [join $line]]
while {[set match [lsearch $line ${temp}!backsp]] != -1} {
set tlength [string length ${temp}!backsp]
set line1 [lrange $line 0 $match]
set slength [string length $line1]
set line1 [string range $line1 0 [expr $slength - $tlength - 2]]
set line2 [string range [lrange $line $match end] [expr $tlength + 1] end]
set line $line1$line2
}
set line [join $line]
putdcc $idx $line
}
close $infile
return
}
### PUB BINDS DATABASE ###
proc var_fserve:func:binds {{vcheck ""}} {
global var_fserve var_fserve_binds
set vtrigs ""
foreach trigger $var_fserve(triggers) {
if {[info exists var_fserve_binds($trigger)]} then {
if {$var_fserve_binds($trigger) != $var_fserve(bind)} then {
unbind pub $var_fserve_binds($trigger) $trigger var_fserve:pub:fserve
unset var_fserve_binds($trigger)
} else {
lappend vtrigs $trigger
}
}
set var_fserve_binds($trigger) $var_fserve(bind)
bind pub $var_fserve(bind) $trigger var_fserve:pub:fserve
lappend vtrigs $trigger
}
foreach trigger [array names var_fserve_binds] {
if {[lsearch -exact $var_fserve(triggers) $trigger] == -1} then {
unbind pub $var_fserve_binds($trigger) $trigger var_fserve:pub:fserve
unset var_fserve_binds($trigger)
}
}
if {$vtrigs != "" && [lsearch -exact $vtrigs $vcheck] == -1} then {
return 0
} else {
return 1
}
}
### FLOOD CONTROL ###
proc var_fserve:func:floodctrl {type {arg ""}} {
global var_fserve var_fserve_floodratio var_fserve_flood
set type [string tolower $type]
if {![string match *var?fserve?func?floodctrl* [string tolower [utimers]]]} then {
utimer 30 "var_fserve:func:floodctrl clean"
}
if {![var_func:imatch or $type "pub" "onjoin" "fserve" "clean"]} then {
return "Invalid type"
} elseif {$type == "fserve"} then {
if {$arg == ""} then {
return -1
}
if {![info exists var_fserve_flood($arg)]} then {
set var_fserve_flood($arg) [unixtime]
return 0
}
set x [lindex [split $var_fserve_floodratio(fserve) :] 0]
set y [lindex [split $var_fserve_floodratio(fserve) :] 1]
set element 0
set templist ""
foreach ts $var_fserve_flood($arg) {
if {[unixtime] - $ts <= $y} then {
lappend templist [lindex $var_fserve_flood($arg) $element]
}
incr element
}
set var_fserve_flood($arg) $templist
lappend var_fserve_flood($arg) [unixtime]
if {[llength $var_fserve_flood($arg)] >= $x} then {
return 1
} else {
return 0
}
}
if {$type == "clean"} then {
set x [lindex [split $var_fserve_floodratio(fserve) :] 0]
set y [lindex [split $var_fserve_floodratio(fserve) :] 1]
foreach entry [array names var_fserve_flood] {
if {![var_func:imatch or $entry "fserve" "onjoin" "pub" "clean"]} then {
continue
}
set length [llength $var_fserve_flood($entry)]
set element 1
foreach ts $var_fserve_flood($entry) {
if {[unixtime] - $ts <= $y} then {
break
} elseif {$element == $length} then {
unset var_fserve_flood($entry)
break
} else {
incr element
}
}
}
return 0
} elseif {![info exists var_fserve_flood($type)]} then {
set var_fserve_flood($type) [unixtime]
return 0
}
set x [lindex [split $var_fserve_floodratio($type) :] 0]
set y [lindex [split $var_fserve_floodratio($type) :] 1]
set element 0
set templist ""
foreach ts $var_fserve_flood($type) {
if {[unixtime] - $ts <= $y} then {
lappend templist [lindex $var_fserve_flood($type) $element]
}
incr element
}
set var_fserve_flood($type) $templist
lappend var_fserve_flood($type) [unixtime]
if {[llength $var_fserve_flood($type)] >= $x} then {
return 1
} else {
return 0
}
}
### ONJOIN ###
bind join $var_fserve(bind) * var_fserve:join:onjoin
proc var_fserve:join:onjoin {nick uhost hand chan} {
global var_fserve
if {[matchattr $hand b] || ($var_fserve(validuser) && $hand == "*") || (!$var_fserve(enable) && !$var_fserve(ad_while_off)) || (!$var_fserve(onjoin)) || [lsearch -exact [string tolower $var_fserve(channels)] [string tolower $chan]] == -1 || [var_fserve:func:floodctrl onjoin]} then {
return 0
}
puthelp "NOTICE $nick :[var_fserve:func:adgen]"
return 0
}
### CHANNEL LINE COUNTER ###
bind pubm -|- * var_fserve:bind:chan-counter
proc var_fserve:bind:chan-counter {1 2 3 chan {args ""}} {
global var_fserve var_fserve_linecount
set chan [string tolower $chan]
if {[lsearch -exact [string tolower $var_fserve(channels)] [string tolower $chan]] == -1} then {
return -1
}
set channels [string tolower $var_fserve(channels)]
foreach channel [array names var_fserve_linecount] {
if {![validchan $channel] || ![botonchan $channel] || [lsearch -exact $channels $channel] == -1} then {
unset var_fserve_linecount($channel)
}
}
if {![info exists var_fserve_linecount($chan)]} then {
set var_fserve_linecount($chan) 1
} else {
incr var_fserve_linecount($chan)
}
return 0
}
proc var_fserve:raw:chan-counter {from keyword text} {
var_fserve:bind:chan-counter 1 2 3 [lindex $text 0]
return 0
}
### TIMED ADVERTISEMENTS ###
proc var_fserve:func:pub-ad {} {
global var_fserve_linecount var_fserve
foreach timer [utimers] {
if {[lindex $timer 1] == "var_fserve:func:pub-ad"} then {
killutimer [lindex $timer 2]
}
}
foreach timer [timers] {
if {[lindex $timer 1] == "var_fserve:func:pub-ad"} then {
killtimer [lindex $timer 2]
}
}
if {[expr int($var_fserve(ad_delay))] == $var_fserve(ad_delay)} then {
timer $var_fserve(ad_delay) var_fserve:func:pub-ad
} else {
utimer [expr int($var_fserve(ad_delay) * 60 + .5)] var_fserve:func:pub-ad
}
if {!$var_fserve(enable) || !$var_fserve(ad)} then {
return
}
set channels [string tolower $var_fserve(channels)]
# For those ircd's that dont like multiple destinations
if {$var_fserve(admode)} then {
foreach channel $channels {
if {!$var_fserve(msg_to_notonchan) && (![validchan $channel] || ![botonchan $channel]) || ![info exists var_fserve_linecount($channel)] || $var_fserve_linecount($channel) < $var_fserve(ad_linemin)} then {
continue
}
set var_fserve_linecount($channel) 0
puthelp "PRIVMSG $channel :[var_fserve:func:adgen]"
}
return
}
set dest ""
foreach channel $channels {
if {!$var_fserve(msg_to_notonchan) && (![validchan $channel] || ![botonchan $channel]) || ![info exists var_fserve_linecount($channel)] || $var_fserve_linecount($channel) < $var_fserve(ad_linemin)} then {
continue
} elseif {[string length dest] > 0} then {
append dest ,$channel
} else {
set dest $channel
}
set var_fserve_linecount($channel) 0
}
if {$dest != ""} then {
puthelp "PRIVMSG $dest :[var_fserve:func:adgen]"
}
return
}
### HOST MASKER ###
proc var_func:maskhost {host options} {
global var_max_nickchars var_max_identchars
set options [split $options .]
set arg1 [lindex $options 0]
set arg2 [lindex $options 1]
set arg3 [lindex $options 2]
set nick [var_func:sindex $host 0 !]
set ident [var_func:sindex $host 1 !@]
set host [var_func:sindex $host 1 @]
switch -- $arg1\
n {
set nickmask $nick
} *n {
set nickmask *[string range $nick [expr [string length $nick] - $var_max_nickchars + 1] end]
} n* {
set nickmask [string range $nick 0 [expr $var_max_nickchars - 2]]*
} *n* {
set nickmask [string range $nick 0 [expr $var_max_nickchars - 2]]*
set nickmask *[string range $nickmask [expr [string length $nickmask] - $var_max_nickchars + 1] end]
} * {
set nickmask *
} default {
return "Invalid syntax"
}
switch -- $arg2\
u {
set identmask $ident
} *u {
if {[string length [string trimleft $ident ~]] > 0} then {
set ident [string trimleft $ident ~]
} elseif {[string length $ident] > 1} then {
set ident [string range $ident 1 end]
}
set identmask *[string range $ident [expr [string length $ident] - $var_max_identchars + 1] end]
} u* {
set identmask [string range $ident 0 [expr $var_max_identchars - 2]]*
} *u* {
if {[string length [string trimleft $ident ~]] > 0} then {
set ident [string trimleft $ident ~]
} elseif {[string length $ident] > 1} then {
set ident [string range $ident 1 end]
}
set identmask [string range $ident 0 [expr $var_max_identchars - 2]]*
set identmask *[string range $identmask [expr [string length $identmask] - $var_max_identchars + 1] end]
} * {
set identmask *
} default {
return "Invalid syntax"
}
switch -- $arg3\
h {
set hostmask $host
} *h {
set hostmask [var_func:sindex [maskhost $host] 1 @]
} * {
set hostmask *
} default {
return "Invalid syntax"
}
return ${nickmask}!${identmask}@${hostmask}
}
### SINDEX & SRANGE (Returns index'th element of a string) ###
proc var_func:sindex {string index {split " "}} {
catch {
join [lrange [split $string $split] $index $index]
} result
return $result
}
proc var_func:srange {string first last {split " "}} {
catch {
join [lrange [split $string $split] $first $last]
} result
return $result
}
### IMATCH ###
proc var_func:imatch {op var args} {
switch -- $op\
or {
foreach arg $args {
if {![string compare $var $arg]} then {
return 1
}
}
return 0
} and {
foreach arg $args {
if {[string compare $var $arg]} then {
return 0
}
}
return 1
} default {
return -1
}
}
### NUMBER FORMATTING ###
proc var_func:nformat {num} {
if {![var_func:validnum $num]} then {
return "Invalid number"
}
set int [lindex [split $num .] 0]
set dec [lindex [split $num .] 1]
if {$dec != ""} then {
set es .
} else {
set es ""
}
set place [expr [string length $int] % 3]
if {!$place} then {
set place 3
}
set charnum 1
foreach char [split $int {}] {
if {$charnum == $place} then {
append int2 ${char},
set charnum 1
set place 3
} else {
append int2 $char
incr charnum
}
}
return [string trimright $int2 ,]${es}$dec
}
### UNIXTIME WITH MS ###
proc var_func:unixtime {{unixtime [unixtime]} {clicks "[clock clicks]"}} {
set n 0
if {$clicks < 0} then {
set clicks [expr abs($clicks)]
set n 1
}
set ms [expr [format "%.3f" [expr double($clicks) / 1000000]] * 1000]
if {$n} then {
set ms [expr 1000 - int([string trimleft $ms 0])]
}
return $unixtime.$ms
}
### BOT IP ###
proc var_func:myip {{format "base256"}} {
global nat-ip
if {$format == "base256" || $format == "quad"} then {
if {![info exists nat-ip] || ${nat-ip} == ""} then {
return [var_func:longip-2-quad [myip]]
} else {
return ${nat-ip}
}
} elseif {$format == "long" || $format == "longip"} then {
if {![info exists nat-ip] || ${nat-ip} == ""} then {
return [myip]
} else {
set splitip [split ${nat-ip} .]
set ip1 [lindex $splitip 0]
set ip2 [lindex $splitip 1]
set ip3 [lindex $splitip 2]
set ip4 [lindex $splitip 3]
return [format %u [expr $ip1*256*256*256 + $ip2*256*256 + $ip3*256 + $ip4]]
}
} else {
return "Invalid type. Available types: base256 and quad, long and longip."
}
}
### DIRECTORY WORK ###
proc var_fserve:func:dir {idx command dir {dir2 ""}} {
global var_fserve_pwd var_fserve
switch -- $command\
isin {
if {$dir2 == ""} then {
set dir2 [var_fserve:func:slots get $idx rootdir]
}
if {![file isdirectory $dir2]} then {
return 0
}
catch {
cd [var_fserve:func:slots get $idx rootdir]/$dir
} pass1
catch {
cd $dir
} pass2
set pwd [pwd]
if {![string length $pass1] && [string match $dir2* $pwd] || ![string length $pass2] && [string match $dir2* $pwd]} then {
cd $var_fserve_pwd
return $pwd
} else {
cd $var_fserve_pwd
return 0
}
} isvalid {
catch {
set var_fserve_pwd [pwd]
set var_fserve_temp1 [catch {cd $var_fserve(mainpath)}]
set var_fserve_temp2 [catch {cd $var_fserve_pwd}]
}
catch {
foreach entry $var_fserve(sections) {
if {[lindex $entry 1] == ""} then {
set var_fserve_temp1 1
} else {
set var_fserve_pwd [pwd]
set var_fserve_tpath "$var_fserve(mainpath)/[lindex $entry 1]"
set var_fserve_temp1 [catch {cd $var_fserve_tpath}]
set var_fserve_temp2 [catch {cd $var_fserve_pwd}]
}
if {$var_fserve_temp1 || $var_fserve_temp2} then break
}
}
return [expr !($var_fserve_temp1 || $var_fserve_temp2)]
} relative {
return /[string trim [string range $dir [string length [var_fserve:func:slots get $idx rootdir]] end] /]
} default {
return -1
}
}
### FSERVE HELP ORGANIZATION ###
proc var_fserve:func:help {{element "all"}} {
global var_fserve
set help_items {
help
ls
dir
get
find
stats
exit
cd
pwd
who
say
login
cp
mv
rm
rmdir
mkdir
}
switch -- $element\
all {
set length 0
foreach entry $help_items {
#set entry [string trim $entry [k][r][o]]
set elength [string length $entry]
if {$elength > $length} then {
set length $elength
}
}
incr length 2
set items_per_line [expr int($var_fserve(maxchars) / $length)]
if {!$items_per_line} then {
incr items_per_line
}
set amount 0
set string "Help for Fserve $var_fserve(ver):\nCommands:\n "
foreach entry $help_items {
set item [format %-${length}s $entry]
if {$amount >= $items_per_line} then {
append string "\n $item"
set amount 0
} else {
append string $item
}
incr amount
}
return $string
} help {
return "### help \[command\]\n Displays a list of available commands. If a command is specified, a detailed description on the command is given, if available."
} ls {
return "### ls \[args\]\n Displays a UNIX-style dir listing."
} dir {
return "### dir\n Displays an MS-DOS-style dir listing."
} get {
return "### get <filename/mask>\n Sends specified file(s) to a user. Wildcards accepted."
} find {
return "### find <mask>\n Searches for files matching a mask. Uses globbing rules."
} stats {
return "### stats\n Displays Fileserver statistics and information."
} exit {
return "### exit\n Exits the Fserve."
} cd {
return "### cd <directory>\n Changes current directory."
} pwd {
return "### pwd\n Displays current directory."
} say {
return "### say <message>\n Sends a message to other users on the Fserve."
} who {
return "### who\n Displays a list of users currently on the Fserve."
} login {
return "### login <password>\n Fserve janitor login."
} cp {
return "### cp <source> <destination>\n Copies file(s) or dir(s). Wildcards accepted. Janitor only."
} mv {
return "### mv <source[u]> <[u]destination[u]>\n Moves file(s) or dir(s). Wildcards accepted. Janitor only."
} rm {
return "### [u]rm[u] <[u]target[u]>\n Deletes file(s). Wildcards accepted. Janitor only."
} rmdir {
return "### [u]rmdir[u] <[u]target[u]>\n Deletes dir(s). Wildcards accepted. Janitor only."
} mkdir {
return "### [u]mkdir[u] <[u]directory[u]>\n Attempts to create a directory. Janitor only."
} default {
if {[lsearch -exact $help_items $element] == -1} then {
return "Invalid help item."
} else {
return "No help available on that."
}
}
}
### FSERVE SIZE CALCULATION ###
proc var_fserve:func:du {} {
global var_fserve var_fserve_stats
set var_fserve_stats(koffered) [lindex [exec du -s $var_fserve(mainpath)] 0]
set files 0
foreach entry [split [exec du -a $var_fserve(mainpath)] \n] {
set name [lindex $entry 1]
if {![file isdirectory $name]} then {
incr files
}
}
set var_fserve_stats(foffered) $files
if {![string match *var?fserve?func?du* [string tolower [timers]]] && $var_fserve(statsref)} then {
timer $var_fserve(statsref) var_fserve:func:du
}
return
}
### FSERVE INDEX GENERATION (STARTUP ONLY)
proc var_fserve:func:genindex {} {
global var_fserve
set cpwd [pwd]
foreach entry $var_fserve(sections) {
if {[lindex $entry 3] != ""} then {
if {[lindex $entry 4] != 1} then {
cd "$var_fserve(mainpath)/[lindex $entry 1]"
set path "$var_fserve(idxpath)/[lindex $entry 3]"
exec echo -e "du -h * >$path~tmp\nsort -k2 $path~tmp >$path~tmp2\nsed -e \"/lost+found/d\" $path~tmp2 >$path\nrm -f $path~tmp*" >$var_fserve(idxpath)/cmd~tmp
exec chmod 700 $var_fserve(idxpath)/cmd~tmp
exec $var_fserve(idxpath)/cmd~tmp
exec rm -f $var_fserve(idxpath)/cmd~tmp
} else {
cd "$var_fserve(mainpath)/[lindex $entry 1]"
set path "$var_fserve(idxpath)/[lindex $entry 3]"
exec echo -e "ls -shRX1 * >$path~tmp\nsed -e \"/lost+found/d\" $path~tmp >$path\nrm -f $path~tmp*" >$var_fserve(idxpath)/cmd~tmp
exec chmod 700 $var_fserve(idxpath)/cmd~tmp
exec $var_fserve(idxpath)/cmd~tmp
exec rm -f $var_fserve(idxpath)/cmd~tmp
}
}
}
cd $cpwd
return 1
}
### FSERVE FUNCTIONS ###
proc var_fserve:func:fserve {command {arg1 ""} {arg2 ""} {arg3 ""}} {
switch -- $command\
ls {
global var_fserve
if {$arg3 != ""} then {
return "### Usage: ls"
}
set length 0
set ls [glob -nocomplain -- [split $arg2]/*]
foreach entry [lsort $ls] {
set elength [string length [file size $entry]]
if {$elength > $length} then {
set length $elength
}
}
set pwd [var_fserve:func:dir $arg1 relative $arg2]
set string "### \[$pwd\]"
set string2 ""
foreach entry [lsort $ls] {
set size [format %${length}s [file size $entry]]
set name [file tail $entry]
if {[file isdirectory $entry]} then {
if {[file tail $entry] != "lost+found"} then {
append name /
append string "\n $size [strftime "%b %d %H:%M" [file mtime $entry]] $name"
}
} else {
append string2 "\n $size [strftime "%b %d %H:%M" [file mtime $entry]] $name"
}
}
append string "$string2"
return $string
} dir {
global var_fserve
if {$arg3 != ""} then {
return "### Usage: dir"
}
set ls [glob -nocomplain -- [split $arg2]/*]
set length 0
foreach entry [lsort $ls] {
set elength [string length [var_func:nformat [file size $entry]]]
if {$elength > $length} then {
set length $elength
}
}
if {$length < 8} then {
set length 8
}
set pwd [var_fserve:func:dir $arg1 relative $arg2]
set string "### Directory of $pwd"
set string2 ""
foreach entry [lsort $ls] {
if {[file isdirectory $entry]} then {
set info [format %-${length}s <DIR>]
} else {
set info [format %${length}s [var_func:nformat [file size $entry]]]
}
set date [strftime %m-%d-%y [file mtime $entry]]
set time [format %6s [string trim [string tolower [strftime %I:%M%p [file mtime $entry]]] 0m]]
if {[file isdirectory $entry]} then {
if {[file tail $entry] != "lost+found"} then {
append string "\n $info $date $time [file tail $entry]"
}
} else {
append string2 "\n $info $date $time [file tail $entry]"
}
}
append string "$string2"
return $string
} stats {
global var_fserve_stats var_fserve
# koffered foffered
set nick [var_fserve:func:slots get $arg1 nick]
set ko [var_func:nformat $var_fserve_stats(koffered)]
set fo [var_func:nformat $var_fserve_stats(foffered)]
set dccs [var_fserve:func:transfers formatted $nick]
return "### Fserve $var_fserve(ver) ###\nStats:\n Fserve was triggered $var_fserve_stats(uses) time(s).\n KB offered: $ko\n Files offered: $fo\n$dccs"
} get {
global var_fserve max-dcc var_fserve_queue
if {$arg2 == ""} then {
return "Usage: get <file/mask>"
}
if {[string index $arg2 0] == "/"} then {
set pwd [var_fserve:func:slots get $arg1 rootdir]
} else {
set pwd [var_fserve:func:slots get $arg1 pwd]
}
set count 0
# arg1 is idx, arg2 is text
set filelist ""
foreach entry [glob -nocomplain -- [split $pwd]/[split $arg2]] {
# set tail [file tail $entry]
set dir [file dirname $entry]
# The above line should obsolete this: set dir [string range $entry 0 [expr [string length $entry] - [string length $tail] - 1]]
if {[var_fserve:func:dir $arg1 isin $dir] == 0 || ![file isfile $entry]} then {
continue
}
foreach jdir $var_fserve(jdirs) {
set result [var_fserve:func:dir $arg1 isin $dir $jdir]
if {$result != 0 && ![var_fserve:func:slots get $idx janitor]} then {
continue
}
}
lappend filelist $entry
incr count
}
if {!$count} then {
return "No matches."
}
set nick [var_fserve:func:slots get $arg1 nick]
set validcount 0
set qdl 0
set qgs 0
set maxdl 0
set maxgs 0
set maxdcc 0
set dccerror 0
set dccerrormsg ""
foreach entry $filelist {
set size [file size $entry]
set downloads [expr [lindex [var_fserve:func:transfers outgoing $nick] 0] + [lindex [var_fserve:func:transfers pendout $nick] 0]]
set totalsends [expr [lindex [var_fserve:func:sendscount] 0]]
if {${max-dcc} <= [dccused]} then {
incr maxdcc
continue
} elseif {$downloads >= $var_fserve(maxdloads)} then {
if {$var_fserve(maxqueue)} then {
if {![array exists var_fserve_queue]} then {
set var_fserve_queue(1) "$nick $entry"
incr qdl
} else {
set queue [expr [array size var_fserve_queue] +1]
if {$queue <= $var_fserve(maxqueue)} then {
set var_fserve_queue($queue) "$nick $entry"
incr qdl
} else {
incr maxdl
}
}
} else {
incr maxdl
}
continue
} elseif {$totalsends <= 0} then {
if {$var_fserve(maxqueue)} then {
if {![array exists var_fserve_queue]} then {
set var_fserve_queue(1) "$nick $entry"
incr qgs
} else {
set queue [expr [array size var_fserve_queue] +1]
if {$queue <= $var_fserve(maxqueue)} then {
set var_fserve_queue($queue) "$nick $entry"
incr qgs
} else {
incr maxgs
}
}
} else {
incr maxgs
}
continue
}
switch -- [dccsend $entry $nick]\
0 {
incr validcount
putdcc $arg1 "Sending file: [file tail $entry]"
} 1 {
incr dccerror
set dccerrormsg "Too many active dcc connections."
continue
} 2 {
incr dccerror
set dccerrormsg "Can't establish dcc connection."
continue
} 3 {
incr dccerror
set dccerrormsg "Specified file doesn't exists."
continue
} 4 {
# Queued. That's not wanted. Kill all DCC's of this user
# and send him info.
set count 0
foreach idx [dcclist] {
if {$nick == [lindex $idx 1]} then {
killdcc [lindex $idx 0]
incr count
}
if {$arg1 == [lindex $idx 0]} then {
killdcc [lindex $idx 0]
incr count
}
}
puthelp "NOTICE $tmpnick :I have killed all ($count) your DCC connection(s) with Fserve because the bot has reached limit of maximum simultaneous DCC's. Please contact Fserve owner."
}
}
putdcc $arg1 "$validcount out of $count matches sent."
if {$maxdcc} then {
putdcc $arg1 "Bot has reached maximum number od dcc slots. $maxdcc matches denied."
}
if {$maxdl || $qdl} then {
if {!$qdl} then {
putdcc $arg1 "You have too many active downloads. $maxdl matches denied."
} elseif {$maxdl} then {
putdcc $arg1 "You have too many active downloads. $qdl matches queued, $maxdl matches not queued because queue is full."
} else {
putdcc $arg1 "You have too many active downloads. $qdl matches queued."
}
}
if {$maxgs || $qgs} then {
if {!$qgs} then {
putdcc $arg1 "All download slots are in use. $maxgs matches denied."
} elseif {$maxgs} then {
putdcc $arg1 "All download slots are in use. $qgs matches queued, $maxgs matches not queued because queue is full."
} else {
putdcc $arg1 "All download slots are in use. $qgs matches queued."
}
}
if {$dccerror} then {
putdcc $arg1 "$dccerrormsg $dccerror matches denied."
}
return
} say {
if {[string trim $arg1] == ""} then {
return "Usage: say <message>"
}
set nick [var_fserve:func:slots get $arg2 nick]
var_fserve:func:uinfo say $arg2 "<$nick> $arg1"
return "Said: $arg1"
} who {
global var_fserve_slots
foreach idx [var_fserve:func:uinfo who] {
append nicklist "[var_fserve:func:slots get $idx nick], "
}
set nicklist [string trimright [join [lsort $nicklist]] ", "]
return "Users online: $nicklist"
} cp {
set pwd1 [var_fserve:func:slots get $arg1 pwd]
if {[string index $arg2 0] == "/"} then {
set pwd1 [var_fserve:func:slots get $arg1 rootdir]
}
set pwd2 [var_fserve:func:slots get $arg1 pwd]
if {[string index $arg3 0] == "/"} then {
set pwd2 [var_fserve:func:slots get $arg1 rootdir]
}
set scount 0
set dcount 0
set copycount 0
set srclist ""
set destlist ""
foreach entry [glob -nocomplain -- [split $pwd1]/[split $arg2]] {
set dir [file dirname $entry]
if {[file isfile $entry] && [var_fserve:func:dir $arg1 isin $dir] == 0 || [file isdirectory $entry] && [var_fserve:func:dir $arg1 isin $entry] == 0} then {
continue
}
lappend srclist $entry
incr scount
}
foreach entry [glob -nocomplain -- [split $pwd2]/[split $arg3]] {
set dir [file dirname $entry]
if {[file isfile $entry] && [var_fserve:func:dir $arg1 isin $dir] == 0 || [file isdirectory $entry] && [var_fserve:func:dir $arg1 isin $entry] == 0} then {
continue
}
lappend destlist $entry
incr dcount
}
if {$destlist == ""} then {
lappend destlist $pwd2/$arg3
}
foreach dest $destlist {
foreach src $srclist {
if {$src != $dest} then {
catch {
file copy -force -- $src $dest
} result
if {$result == ""} then {
incr copycount
}
}
}
}
return "### Copied $copycount object(s) out of $scount total matching object(s) to $dcount matching destination(s)."
} mv {
set pwd1 [var_fserve:func:slots get $arg1 pwd]
if {[string index $arg2 0] == "/"} then {
set pwd1 [var_fserve:func:slots get $arg1 rootdir]
}
set pwd2 [var_fserve:func:slots get $arg1 pwd]
if {[string index $arg3 0] == "/"} then {
set pwd2 [var_fserve:func:slots get $arg1 rootdir]
}
set scount 0
set dcount 0
set movecount 0
set srclist ""
set destlist ""
foreach entry [glob -nocomplain -- [split $pwd1]/[split $arg2]] {
set dir [file dirname $entry]
if {[file isfile $entry] && [var_fserve:func:dir $arg1 isin $dir] == 0 || [file isdirectory $entry] && [var_fserve:func:dir $arg1 isin $entry] == 0} then {
continue
}
lappend srclist $entry
incr scount
}
foreach entry [glob -nocomplain -- [split $pwd2]/[split $arg3]] {
set dir [file dirname $entry]
if {[file isfile $entry] && [var_fserve:func:dir $arg1 isin $dir] == 0 || [file isdirectory $entry] && [var_fserve:func:dir $arg1 isin $entry] == 0} then {
continue
}
lappend destlist $entry
incr dcount
}
if {$destlist == ""} then {
lappend destlist $pwd2/$arg3
}
foreach dest $destlist {
foreach src $srclist {
if {$src != $dest} then {
catch {
file rename -force -- $src $dest
} result
if {$result == ""} then {
incr movecount
}
}
}
}
return "### Moved $movecount object(s) out of $scount total matching object(s) to $dcount matching destination(s)."
} rm {
set pwd [var_fserve:func:slots get $arg1 pwd]
if {[string index $arg2 0] == "/"} then {
set pwd [var_fserve:func:slots get $arg1 rootdir]
}
set count 0
foreach entry [glob -nocomplain -- [split $pwd]/[split $arg2]] {
set dir [file dirname $entry]
#set tail [file tail $entry]
#set dir [string range $entry 0 [expr [string length $entry] - [string length $tail] - 1]]
if {[var_fserve:func:dir $arg1 isin $dir] == 0 || ![file isfile $entry]} then {
continue
}
file delete -- $entry
incr count
}
return "### Deleted $count file(s)"
} rmdir {
set pwd [var_fserve:func:slots get $arg1 pwd]
if {[string index $arg2 0] == "/"} then {
set pwd [var_fserve:func:slots get $arg1 rootdir]
}
set count 0
foreach entry [glob -nocomplain -- [split $pwd]/[split $arg2]] {
#set dir [file dirname $entry]
#set tail [file tail $entry]
#set dir [string range $entry 0 [expr [string length $entry] - [string length $tail] - 1]]
if {[var_fserve:func:dir $arg1 isin $entry] == 0 || [var_fserve:func:dir $arg1 isin $entry] == [var_fserve:func:slots get $arg1 rootdir] || ![file isdirectory $entry]} then {
continue
}
file delete -force -- $entry
putdcc $arg1 "Deleted dir: [var_fserve:func:dir $arg1 relative $entry]"
incr count
}
return "### Deleted $count dir(s)"
} mkdir {
set pwd [var_fserve:func:slots get $arg1 pwd]
if {[string index $arg2 0] == "/"} then {
set pwd [var_fserve:func:slots get $arg1 rootdir]
}
set count 0
set dirs [file dirname $arg2]
set dest [file tail $arg2]
set result [glob -nocomplain -- [split $pwd]/[split $dirs]]
if {[llength $result] <= 1} then {
putdcc $arg1 "### Single dir mode."
if {$result == ""} then {
catch {
set exists [file exists [var_fserve:func:slots get $arg1 rootdir]/$arg2]
file mkdir [var_fserve:func:slots get $arg1 rootdir]/$arg2
set dest [var_fserve:func:slots get $arg1 rootdir]
} result
} else {
catch {
set exists [file exists $result/$dest]
file mkdir $result/$dest
set dest $result
} result
}
if {[string match error* $result] || $exists} then {
return "Destination already exists."
} elseif {[var_fserve:func:dir $arg1 isin $dest] == 0} then {
file delete -force -- $dest/$arg2
return "Invalid path."
}
return "### Created dir: [var_fserve:func:dir $arg1 relative [file dirname $dest]/$arg2]"
} else {
putdcc $arg1 "### Multidir mode."
foreach entry $result {
set dir [file dirname $entry]
if {[var_fserve:func:dir $arg1 isin $dir] == 0 || [file exists $entry/$dest]} then {
continue
}
file mkdir $entry/$dest
putdcc $arg1 "Created [var_fserve:func:dir $arg1 relative $entry/$dest]"
incr count
}
return "### Created $count dir(s)"
}
} default {
return "Invalid command."
}
}
### FSERVE SLOTS MANAGEMENT ###
proc var_fserve:func:slots {command idx {element ""} {data ""}} {
global var_fserve_slots
set command [string tolower $command]
if {![var_func:validnum $idx] && ![var_func:imatch or $command "isonfserve" "addpend" "delpend" "ispend"]} then {
return -1
}
switch -- $command\
set {
if {$data == "" || $element == "" || [llength $data] > 6 || (![info exists var_fserve_slots($idx)] && $element != "all" && $command != "isonfserve") || ($command != "isonfserve" && ![var_func:imatch or $element "all" "nick" "mask" "pwd" "idle" "janitor"])} then {
return -1
} elseif {$element == "all"} then {
if {[llength $data] != 6 || ![var_func:validnum [lindex $data 3]] || ![var_func:validnum [lindex $data 4]]} then {
return -1
}
set var_fserve_slots($idx) $data
return 1
}
# Check for ([llength $data] > 1) was removed
switch -- $element\
nick {
set index 0
} host {
set index 1
} pwd {
set index 2
} idle {
set index 3
if {![var_func:validnum $data]} then {
return -1
}
} janitor {
set index 4
if {$data != 0 && $data != 1} then {
return -1
}
}
set var_fserve_slots($idx) [lreplace $var_fserve_slots($idx) $index $index $data]
return 1
} get {
if {![info exists var_fserve_slots($idx)]} then {
return 0
} elseif {![var_func:imatch or $element "all" "nick" "host" "pwd" "idle" "janitor" "rootdir"]} then {
return -1
} elseif {$element == "all"} then {
return $var_fserve_slots($idx)
}
switch -- $element\
nick {
set index 0
} host {
set index 1
} pwd {
set index 2
} idle {
set index 3
} janitor {
set index 4
} rootdir {
set index 5
}
return [lindex $var_fserve_slots($idx) $index]
} isonfserve {
if {![info exists var_fserve_slots]} then {
return 0
} elseif {$element == "masked"} then {
set idx [var_func:maskhost n!$idx *.*u.*h]
}
set idx [string tolower $idx]
set count 0
foreach entry [array names var_fserve_slots] {
if {[string match [string tolower $idx] [var_func:sindex [string tolower [lindex $var_fserve_slots($entry) 1]] 1 @]]} then {
incr count
}
}
return $count
} addpend {
if {$idx == ""} then {
return -1
} elseif {![info exists var_fserve_slots(pending)]} then {
set var_fserve_slots(pending) ""
}
lappend var_fserve_slots(pending) "[unixtime] $idx"
} delpend {
if {$idx == ""} then {
return -1
} elseif {![info exists var_fserve_slots(pending)]} then {
return
}
set success 0
set templist ""
foreach entry [string tolower $var_fserve_slots(pending)] {
if {[string tolower [lindex $entry 1]] == [string tolower $idx] && !$success} then {
set success 1
} else {
lappend templist $entry
}
}
set var_fserve_slots(pending) $templist
return
} ispend {
if {![info exists var_fserve_slots(pending)]} then {
return 0
}
set count 0
foreach entry [string tolower $var_fserve_slots(pending)] {
if {[string tolower [lindex $entry 1]] == [string tolower $idx]} then {
incr count
}
}
return $count
} default {
return -1
}
}
proc var_fserve:func:pendclean {} {
global var_fserve_slots
if {![info exists var_fserve_slots(pending)]} then {
return
}
foreach entry $var_fserve_slots(pending) {
if {[unixtime] - [lindex $entry 0] >= 30} then {
var_fserve:func:slots delpend [lindex $entry 1]
}
}
if {![string match *var?fserve?func?pendclean* [string tolower [utimers]]]} then {
utimer 30 var_fserve:func:pendclean
}
}
### STATS INIT ###
proc var_fserve:func:stats-init {} {
global var_fserve var_fserve_stats
if {![info exists var_fserve_stats]} then {
set var_fserve_stats(uses) 0
set var_fserve_stats(koffered) 0
set var_fserve_stats(foffered) 0
set var_fserve_stats(ksnagged) 0
set var_fserve_stats(krecieved) 0
set var_fserve_stats(reenable) 0
set var_fserve_stats(wasenabled) $var_fserve(enable)
set var_fserve_stats(lock) 0
}
return
}
### DCC COMMANDS ###
# !list
bind pub $var_fserve(bind) !list var_fserve:pub:list
proc var_fserve:pub:list {nick uhost hand chan text} {
puthelp "NOTICE $nick :[var_fserve:func:adgen]"
return 1
}
bind dcc j|- fhelp var_dcc:fhelp
bind dcc j|- fstat var_dcc:fstat
bind dcc j|- fwho var_dcc:fwho
bind dcc j|- fcount var_dcc:fcount
bind dcc j|- findex var_dcc:findex
bind dcc j|- fad var_dcc:fad
bind dcc j|- fban var_dcc:fban
bind dcc j|- funban var_dcc:funban
bind dcc j|- fbans var_dcc:fbans
bind dcc j|- fon var_dcc:fon
bind dcc j|- foff var_dcc:foff
proc var_dcc:fhelp {hand idex text} {
putdcc $idex "Available Fserve commands:"
putdcc $idex "fstat - shows current transfer statistics"
putdcc $idex "fwho - shows who is currently connected via chat"
putdcc $idex "fcount - count how many files/megabytes fserve is offering"
putdcc $idex "findex - create index files for all fserve sections"
putdcc $idex "fad - shows current ad message"
putdcc $idex "fban - add fserve ban"
putdcc $idex "funban - remove specified fserve ban"
putdcc $idex "fbans - show all fserve bans"
putdcc $idex "fon - enable fserve"
putdcc $idex "foff - disable fserve"
putdcc $idex "fhelp - shows this help"
}
proc var_dcc:findex {hand idex text} {
global var_fserve
set cpwd [pwd]
putdcc $idex "$text"
foreach entry $var_fserve(sections) {
if {[lindex $entry 3] != ""} then {
if {[lindex $entry 4] != 1} then {
cd "$var_fserve(mainpath)/[lindex $entry 1]"
set path "$var_fserve(idxpath)/[lindex $entry 3]"
exec echo -e "du -h * >$path~tmp\nsort -k2 $path~tmp >$path~tmp2\nsed -e \"/lost+found/d\" $path~tmp2 >$path\nrm -f $path~tmp*" >$var_fserve(idxpath)/cmd~tmp
exec chmod 700 $var_fserve(idxpath)/cmd~tmp
exec $var_fserve(idxpath)/cmd~tmp
exec rm -f $var_fserve(idxpath)/cmd~tmp
putdcc $idex "Index file '[lindex $entry 3]' for fserve '[lindex $entry 0]' created."
} else {
cd "$var_fserve(mainpath)/[lindex $entry 1]"
set path "$var_fserve(idxpath)/[lindex $entry 3]"
exec echo -e "ls -shRX1 * >$path~tmp\nsed -e \"/lost+found/d\" $path~tmp >$path\nrm -f $path~tmp*" >$var_fserve(idxpath)/cmd~tmp
exec chmod 700 $var_fserve(idxpath)/cmd~tmp
exec $var_fserve(idxpath)/cmd~tmp
exec rm -f $var_fserve(idxpath)/cmd~tmp
putdcc $idex "Index file '[lindex $entry 3]' for fserve '[lindex $entry 0]' created."
}
}
}
cd $cpwd
}
proc var_dcc:fcount {hand idex text} {
var_fserve:func:du
putdcc $idex "Stats refreshed."
}
proc var_dcc:fad {hand idex text} {
putdcc $idex [var_fserve:func:adgen]
}
proc var_dcc:fstat {hand idex text} {
global var_fserve_queue
putdcc $idex [var_fserve:func:transfers formatted $text]
if {[array size var_fserve_queue]} then {
putdcc $idex "### Queue:"
foreach entry [lsort [array names var_fserve_queue]] {
putdcc $idex "-> Filename: [file tail [lindex $var_fserve_queue($entry) 1]] to [lindex $var_fserve_queue($entry) 0]."
putdcc $idex " [file size [lindex $var_fserve_queue($entry) 1]] bytes."
}
} else {
putdcc $idex "### Queue is empty."
}
}
proc var_dcc:fwho {hand idex text} {
global var_fserve_slots
set nicklist ""
foreach idx [var_fserve:func:uinfo who] {
append nicklist "[var_fserve:func:slots get $idx nick], "
}
set nicklist [string trimright [join [lsort $nicklist]] ", "]
putdcc $idex "### Users connected to fserve:"
putdcc $idex "$nicklist"
}
proc var_dcc:fban {hand idex text} {
global var_fserve var_fserve_bans
if {$text == ""} then {
putdcc $idex "Usage: fban <hostmask> \[reason\]"
return 0
} else {
set var_fserve_bans([expr [array size var_fserve_bans] + 1]) "[lindex $text 0] [lrange $text 1 end]"
set fd [open $var_fserve(banfile) "w"]
foreach entry [lsort [array names var_fserve_bans]] {
puts $fd "[lindex $var_fserve_bans($entry) 0] [lrange $var_fserve_bans($entry) 1 end]"
}
close $fd
if {[lindex $var_fserve_bans($entry) 1] != ""} then {
putdcc $idex "Added ban for [lindex $text 0] with reason \"[lrange $text 1 end]\"."
} else {
putdcc $idex "Added ban for [lindex $text 0] with no reason."
}
}
}
proc var_dcc:funban {hand idex text} {
global var_fserve var_fserve_bans
if {$text == ""} then {
putdcc $idex "Usage: funban <ban number>"
return 0
} else {
if {![array size var_fserve_bans]} then {
putdcc $idex "No bans."
return 0
}
set ban ""
foreach entry [lsort [array names var_fserve_bans]] {
if {$entry == [lindex $text 0]} then {
set ban [lindex $var_fserve_bans($entry) 0]
}
if {$entry > [lindex $text 0]} then {
set var_fserve_bans([expr $entry - 1]) $var_fserve_bans($entry)
}
}
if {[array size var_fserve_bans] > 0 && $ban != ""} then {
unset var_fserve_bans([array size var_fserve_bans])
}
set fd [open $var_fserve(banfile) "w"]
foreach entry [lsort [array names var_fserve_bans]] {
puts $fd "[lindex $var_fserve_bans($entry) 0] [lrange $var_fserve_bans($entry) 1 end]"
}
close $fd
if {$ban != ""} then {
putdcc $idex "Removed ban for $ban."
} else {
putdcc $idex "No such ban."
}
}
}
proc var_dcc:fbans {hand idex text} {
global var_fserve var_fserve_bans
if {[array size var_fserve_bans]} then {
putdcc $idex "Current bans:"
foreach entry [lsort [array names var_fserve_bans]] {
if {[lindex $var_fserve_bans($entry) 1] != ""} then {
putdcc $idex "$entry. [lindex $var_fserve_bans($entry) 0] ([lrange $var_fserve_bans($entry) 1 end])"
} else {
putdcc $idex "$entry. [lindex $var_fserve_bans($entry) 0]"
}
}
} else {
putdcc $idex "No bans."
}
}
proc var_dcc:fon {hand idex text} {
global var_fserve
if {$var_fserve(enable)} then {
putdcc $idex "Fserve already enabled."
} else {
set var_fserve(enable) 1
}
}
proc var_dcc:foff {hand idex text} {
global var_fserve
if {$var_fserve(enable)} then {
set var_fserve(enable) 0
} else {
putdcc $idex "Fserve already disabled."
}
}
### DCC TRANSFERS ###
proc var_fserve:func:transfers {type {nick ""}} {
switch -- $type\
outgoing {
set gets 0
set output ""
foreach entry [dcclist GET] {
if {$nick != "" && [string tolower [lindex $entry 1]] != [string tolower $nick]} then {
continue
}
set olist ""
set file [lrange [lindex $entry 4] 2 end]
set whom [lindex $entry 1]
set sent [string trim [lindex [split [lindex [lindex $entry 4] 1] /] 0] ()]
set total [lindex [split [lindex [lindex $entry 4] 1] /] 1]
lappend olist $whom $file $sent $total
lappend output $olist
incr gets
}
set output [linsert $output 0 $gets]
return $output
} pendout {
set gets 0
set output ""
foreach entry [dcclist GET_PENDING] {
if {$nick != "" && [string tolower [lindex $entry 1]] != [string tolower $nick]} then {
continue
}
set olist ""
set file [lrange [lindex $entry 4] 2 end]
set whom [lindex $entry 1]
set sent [string trim [lindex [split [lindex [lindex $entry 4] 1] /] 0] ()]
set total [lindex [split [lindex [lindex $entry 4] 1] /] 1]
lappend olist $whom $file $sent $total
lappend output $olist
incr gets
}
set output [linsert $output 0 $gets]
return $output
} formatted {
set outgoing [var_fserve:func:transfers outgoing $nick]
set outcount [lindex $outgoing 0]
set outgoing [lreplace $outgoing 0 0]
set output ""
if {!$outcount && $nick == ""} then {
append output "\n### No outgoing transfers."
} elseif {!$outcount && $nick != ""} then {
append output "\n### No outgoing transfers for $nick."
} else {
if {$nick == ""} then {
append output "\n### Outgoing transfers:"
} else {
append output "\n### Outgoing transfers for $nick:"
}
foreach entry $outgoing {
set whom [lindex $entry 0]
set filename [file tail [lindex $entry 1]]
set sent [lindex $entry 2]
set total [lindex $entry 3]
set percentage [expr int([format %.3f [expr double($sent) / 1024]] * 100 / [format %.3f [expr double($total) / 1024]])]
append output "\n-> $filename to $whom.\n [var_func:nformat $sent] out of [var_func:nformat $total] bytes ($percentage%)."
}
}
if {$outcount} then {
append output "\n### $outcount DCC send(s)."
}
return $output
} default {
return -1
}
}
### PUB FSERVE ###
proc var_fserve:pub:fserve {nick uhost hand chan text} {
global var_fserve max-dcc var_fserve_queue var_fserve_stats var_fserve_bans
# Took out: ![var_fserve:func:binds $lastbind]
# Tracing the settings should make this redundant
if {[matchattr $hand b] || ($var_fserve(validuser) && $hand == "*") || [var_fserve:func:floodctrl pub]} then {
return 0
}
if {!$var_fserve(enable)} then {
puthelp "NOTICE $nick :Fserve is currently OFFLINE"
return 0
}
foreach entry [lsort [array names var_fserve_bans]] {
if {[string match "[lindex $var_fserve_bans($entry) 0]" "$nick!$uhost"]} then {
puthelp "NOTICE $nick :Banned: [lrange $var_fserve_bans($entry) 1 end]"
return 0
}
}
if {[lindex $text 0] == ""} then {
puthelp "NOTICE $nick :Welcome to \02$var_fserve(name)\02 $nick."
puthelp "NOTICE $nick :Usage:"
puthelp "NOTICE $nick :!trigger name - access specified fserve section"
puthelp "NOTICE $nick :!trigger name index - get index file for specified fserve section"
puthelp "NOTICE $nick :!trigger info - show current info about chat/send/queue slots"
set string "Available triggers:"
foreach entry $var_fserve(triggers) {
append string " \02$entry\02"
}
puthelp "NOTICE $nick :$string"
puthelp "NOTICE $nick :Available fserve sections:"
foreach entry $var_fserve(sections) {
if {[lindex $entry 2] == ""} then {
puthelp "NOTICE $nick : \02[lindex $entry 0]\02"
} else {
puthelp "NOTICE $nick : \02[lindex $entry 0]\02 ([lindex $entry 2])"
}
}
puthelp "NOTICE $nick :$string"
return 0
} elseif {[lindex $text 0] == "info"} then {
set string "\02[var_fserve:func:slotcount] of $var_fserve(maxslots)\02 chat slots available."
append string " \02[var_fserve:func:sendscount] of $var_fserve(maxsends)\02 send slots available."
if {$var_fserve(maxqueue)} then {
append string " \02[expr $var_fserve(maxqueue) - [array size var_fserve_queue]] of $var_fserve(maxqueue)\02 queue slots available."
}
append string " Currently offering \02[format %ld [expr $var_fserve_stats(koffered) / 1024]]\02 MB in \02[var_func:nformat $var_fserve_stats(foffered)]\02 files."
puthelp "NOTICE $nick :$string"
set sends 0
foreach entry [dcclist] {
if {[lindex $entry 3] == "GET"} then {
if {!$sends} then {
puthelp "NOTICE $nick :Active sends:"
}
set sent [string trim [lindex [split [lindex [lindex $entry 4] 1] /] 0] ()]
set total [lindex [split [lindex [lindex $entry 4] 1] /] 1]
set percentage [expr int([format %.3f [expr double($sent) / 1024]] * 100 / [format %.3f [expr double($total) / 1024]])]
incr sends
puthelp "NOTICE $nick :$sends. [var_func:nformat $sent] of [var_func:nformat $total] bytes completed ($percentage%)."
}
if {[lindex $entry 3] == "GET_PENDING"} then {
if {!$sends} then {
puthelp "NOTICE $nick :Active sends:"
}
incr sends
puthelp "NOTICE $nick :$sends. Awaiting acknowledgement from user."
}
}
if {!$sends} then {
puthelp "NOTICE $nick :No active sends."
}
if {$var_fserve(maxqueue)} then {
if {[array size var_fserve_queue]} then {
puthelp "NOTICE $nick :Queue slots:"
foreach entry [lsort [array names var_fserve_queue]] {
puthelp "NOTICE $nick :$entry. [var_func:nformat [file size [lindex $var_fserve_queue($entry) 1]]] bytes"
}
} else {
puthelp "NOTICE $nick :Queue is empty."
}
}
return 0
} elseif {[lindex $text 1] == "index"} then {
set path ""
foreach entry $var_fserve(sections) {
if {[lindex $entry 0] == [lindex $text 0]} then {
if {[lindex $entry 3] == ""} then {
puthelp "NOTICE $nick :No index file for this section of file server."
return 0
}
set path "$var_fserve(idxpath)/[lindex $entry 3]"
puthelp "NOTICE $nick :Sending index file [lindex $entry 3]."
}
}
if {$path != ""} then {
dccsend $path $nick
return 0
} else {
set count 0
}
} else {
set count 0
foreach entry $var_fserve(sections) {
if {[lindex $entry 0] == [lindex $text 0]} then {
set temp_path "$var_fserve(mainpath)/[lindex $entry 1]"
incr count
}
}
}
if {!$count} then {
puthelp "NOTICE $nick :\02[lindex $text 0]\02 - no such Fserve."
return 0
}
if {$temp_path == ""} then {
puthelp "NOTICE $nick :Unable to access '[lindex $text 0]'. Please contact Fserve owner."
return 0
}
if {[dccused] >= ${max-dcc}} then {
puthelp "NOTICE $nick :Sorry, maximum amount of dcc slots are in use."
return 0
} elseif {[var_fserve:func:slotcount] < 1} then {
puthelp "NOTICE $nick :Sorry, all $var_fserve(maxslots) slots are full."
return 0
} elseif {([var_fserve:func:slots isonfserve [var_func:sindex $uhost 1 @]] + [var_fserve:func:slots ispend $uhost]) >= $var_fserve(maxclone)} then {
puthelp "NOTICE $nick :Maximum amount of connections from the same address has been reached."
return 0
}
var_fserve:fserv:init $nick $uhost $temp_path
return 1
}
### FSERVE INIT ###
proc var_fserve:fserv:init {nick uhost temp_path} {
global var_fserve
putserv "NOTICE $nick :Initiating DCC chat..."
var_fserve:func:slots addpend $uhost
if {$var_fserve(minport) && $var_fserve(minport)} then {
set port [listen [expr $var_fserve(minport) + [rand [expr $var_fserve(maxport) - $var_fserve(minport)]]] script null]
} else {
set port [listen 0 script null]
}
listen $port off
listen $port script "var_fserve:listen:init [split $nick] [split $uhost] [split $temp_path] $port"
utimer 30 "catch {listen $port off}"
putserv "PRIVMSG $nick :\001DCC CHAT chat [var_func:myip long] $port\001"
return 0
}
proc var_fserve:listen:init {nick uhost temp_path port idx} {
global var_fserve var_fserve_stats
listen $port off
var_fserve:func:slots delpend $uhost
set hostmask [var_func:maskhost $nick!$uhost *.*u.*h]
var_fserve:func:slots set $idx all "$nick $uhost $temp_path [unixtime] 0 $temp_path"
incr var_fserve_stats(uses)
var_fserve:func:idleman $idx clean
if {$var_fserve(maxidle) < 31} then {
utimer $var_fserve(maxidle) "var_fserve:func:idleman $idx kill"
} else {
utimer [expr $var_fserve(maxidle) - 30] "var_fserve:func:idleman $idx warn"
}
var_fserve:func:motd $idx
var_fserve:func:uinfo say $idx "*** $nick has connected to the Fserve."
control $idx "var_fserve:control:fserve [split $nick] [split $uhost]"
return 0
}
proc var_fserve:control:fserve {nick uhost idx text} {
global var_fserve_slots var_fserve var_fserve_stats
var_fserve:func:idleman $idx clean
if {[var_fserve:func:floodctrl fserve $idx] && ![var_fserve:func:slots get $idx janitor]} then {
var_fserve:func:ukill $idx 0 0 "Flood."
return 1
}
var_fserve:func:slots set $idx idle [unixtime]
if {$var_fserve(maxidle) < 31} then {
utimer $var_fserve(maxidle) "var_fserve:func:idleman $idx kill"
} else {
utimer [expr $var_fserve(maxidle) - ([var_fserve:func:slots get $idx janitor] ? 0 : 30)] "var_fserve:func:idleman $idx warn"
}
if {$var_fserve_stats(lock) && $text != ""} then {
putdcc $idx "Fserve is currently locked."
return 0
} elseif {$text == ""} then {
var_fserve:func:ukill $idx 0 1
return 1
}
set string $text
set text [string trimleft $text]
set command [string tolower [var_func:sindex $text 0]]
set text [var_func:srange $text 1 end]
if {$command == "" && $string != ""} then {
set command .
}
switch -- $command\
"" {
# Bah. This seems like an eggdrop bug or something. At this point, all our idx's are considered invalid for some reason.
var_fserve:func:ukill $idx 0 1
return 1
} help {
if {[llength $text] > 1 || $text == ""} then {
putdcc $idx [var_fserve:func:help all]
} else {
putdcc $idx [var_fserve:func:help $text]
}
return 0
} ls {
set pwd [var_fserve:func:slots get $idx pwd]
putdcc $idx [var_fserve:func:fserve ls $idx $pwd]
return 0
} dir {
set pwd [var_fserve:func:slots get $idx pwd]
putdcc $idx [var_fserve:func:fserve dir $idx $pwd]
return 0
} find {
if {$text == ""} then {
putdcc $idx "Usage: find <mask>"
return 0
}
set pwd [var_fserve:func:slots get $idx pwd]
set result [var_func:ffind $idx $pwd $text [var_fserve:func:slots get $idx janitor]]
putdcc $idx "Matches for $text:"
set coun