From 100cb2c7e3c0f27d0edffa7df1da3405d99b1378 Mon Sep 17 00:00:00 2001 From: blackwind Date: Mon, 16 Apr 2012 05:11:40 -0600 Subject: [PATCH 1/8] Added support for bind msg/msgm. --- modules/modtcl.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/modtcl.cpp b/modules/modtcl.cpp index 9b3d913c..6d5179fc 100644 --- a/modules/modtcl.cpp +++ b/modules/modtcl.cpp @@ -79,6 +79,7 @@ public: interp = Tcl_CreateInterp(); Tcl_Init(interp); Tcl_CreateCommand(interp, "Binds::ProcessPubm", tcl_Bind, this, NULL); + Tcl_CreateCommand(interp, "Binds::ProcessMsgm", tcl_Bind, this, NULL); Tcl_CreateCommand(interp, "Binds::ProcessTime", tcl_Bind, this, NULL); Tcl_CreateCommand(interp, "Binds::ProcessEvnt", tcl_Bind, this, NULL); Tcl_CreateCommand(interp, "Binds::ProcessNick", tcl_Bind, this, NULL); @@ -186,6 +187,19 @@ public: return CONTINUE; } + virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage) { + CString sMes = TclEscape(sMessage); + CString sNick = TclEscape(CString(Nick.GetNick())); + CString sHost = TclEscape(CString(Nick.GetIdent() + "@" + Nick.GetHost())); + + CString sCommand = "Binds::ProcessMsgm {" + sNick + "} {" + sHost + "} - {" + sMes + "}"; + i = Tcl_Eval(interp, sCommand.c_str()); + if (i != TCL_OK) { + PutModule(Tcl_GetStringResult(interp)); + } + return CONTINUE; + } + virtual void OnNick(const CNick& OldNick, const CString& sNewNick, const vector& vChans) { CString sOldNick = TclEscape(CString(OldNick.GetNick())); CString sNewNickTmp = TclEscape(sNewNick); From 9b0ac1ab19b915bc72b4c1694eb8e91ca49cf236 Mon Sep 17 00:00:00 2001 From: blackwind Date: Mon, 16 Apr 2012 05:12:25 -0600 Subject: [PATCH 2/8] Added support for bind msg/msgm. --- modules/modtcl/binds.tcl | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/modules/modtcl/binds.tcl b/modules/modtcl/binds.tcl index faa688d9..a55cc5c6 100644 --- a/modules/modtcl/binds.tcl +++ b/modules/modtcl/binds.tcl @@ -6,7 +6,7 @@ # # Binds module to process incoming messages with ZNC modtcl # -# Supported bind types: pubm/pub, time, evnt, nick, bot, dcc, kick +# Supported bind types: pub/pubm, msg/msgm, time, evnt, nick, bot, dcc, kick # evnt: prerehash,rehash,init-server,disconnect-server # @@ -19,7 +19,7 @@ namespace eval Binds { # procs proc Add {type flags cmd {procname ""}} { - if {![regexp {^(pub|pubm|nick|mode|raw|bot|time|evnt|dcc|kick)$} $type]} { + if {![regexp {^(pub|pubm|msg|msgm|nick|mode|raw|bot|time|evnt|dcc|kick)$} $type]} { PutModule "Tcl error: Bind type: $type not supported" return } @@ -53,13 +53,29 @@ namespace eval Binds { } foreach {type flags mask hits proc} [join [binds pubm]] { regsub {^%} $mask {*} mask - if {[ModuleLoaded crypt]} {regsub {^¤} $nick {} nick} + if {[ModuleLoaded crypt]} {regsub {^\244} $nick {} nick} if {[string match -nocase $mask "$channel $text"]} { $proc $nick $user $handle $channel $text } } } + proc ProcessMsgm {nick user handle text} { + # Loop bind list and execute + foreach n [binds msg] { + if {[string match [lindex $n 2] [lindex [split $text] 0]]} { + [lindex $n 4] $nick $user $handle [lrange [join $text] 1 end] + } + } + foreach {type flags mask hits proc} [join [binds msgm]] { + regsub {^%} $mask {*} mask + if {[ModuleLoaded crypt]} {regsub {^\244} $nick {} nick} + if {[string match -nocase $mask "$text"]} { + $proc $nick $user $handle $text + } + } + } + proc ProcessTime {} { if {[clock format [clock seconds] -format "%S"] != 0} {return} set time [clock format [clock seconds] -format "%M %H %d %m %Y"] @@ -137,4 +153,4 @@ proc ::unbind {type flags cmd procname} {Binds::Del $type $flags $cmd $procname} proc ::binds {{type ""}} {if {$type != ""} {set type "$type "};return [lsearch -all -inline $Binds::List "$type*"]} proc ::bindlist {{type ""}} {foreach bind $Binds::List {PutModule "$bind"}} -PutModule "modtcl script loaded: Binds v0.1" +PutModule "modtcl script loaded: Binds v0.2" From 2df8c9ebe8e3870f25b423da98013d99f89e72fc Mon Sep 17 00:00:00 2001 From: blackwind Date: Mon, 16 Apr 2012 06:31:53 -0600 Subject: [PATCH 3/8] puthelp is no longer restricted to channels. --- modules/modtcl/modtcl.tcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/modtcl/modtcl.tcl b/modules/modtcl/modtcl.tcl index 254e43cb..f1f3bfc8 100644 --- a/modules/modtcl/modtcl.tcl +++ b/modules/modtcl/modtcl.tcl @@ -32,7 +32,7 @@ proc puthelp {text {option ""}} { if {[regexp -nocase {^(?:privmsg|notice) (\S+) :(.*)} $text . target line]} { if {$target == "*modtcl"} {PutModule $line; return} if {$target == "*status"} {PutStatus $line; return} - if {[botonchan $target]} {PutUser ":$::botnick![getchanhost $::botnick] $text"} + if {[string index $target 0] != "#" || [botonchan $target]} {PutUser ":$::botnick![getchanhost $::botnick] $text"} } PutIRC $text } @@ -83,7 +83,7 @@ proc botisvoice {{channel ""}} {return [isvoice $::botnick $channel]} proc PermCheck {nick perm channel} { if {$channel == ""} {set channel [channels]} - if {[ModuleLoaded crypt]} {regsub {^¤} $nick {} nick} + if {[ModuleLoaded crypt]} {regsub {^�} $nick {} nick} foreach c $channel { foreach u [GetChannelUsers $c] { if {[string match -nocase $nick [lindex $u 0]] && [string match *$perm* [lindex $u 3]]} { From f65cc2731ad0015660101d4c00bbbd786dffdd45 Mon Sep 17 00:00:00 2001 From: blackwind Date: Mon, 16 Apr 2012 06:37:26 -0600 Subject: [PATCH 4/8] Escaped crypt module token. --- modules/modtcl/modtcl.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/modtcl/modtcl.tcl b/modules/modtcl/modtcl.tcl index f1f3bfc8..fa18bdb9 100644 --- a/modules/modtcl/modtcl.tcl +++ b/modules/modtcl/modtcl.tcl @@ -83,7 +83,7 @@ proc botisvoice {{channel ""}} {return [isvoice $::botnick $channel]} proc PermCheck {nick perm channel} { if {$channel == ""} {set channel [channels]} - if {[ModuleLoaded crypt]} {regsub {^�} $nick {} nick} + if {[ModuleLoaded crypt]} {regsub {^\244} $nick {} nick} foreach c $channel { foreach u [GetChannelUsers $c] { if {[string match -nocase $nick [lindex $u 0]] && [string match *$perm* [lindex $u 3]]} { From f377197a47349342b3faaf46ae77d7868b30b5f9 Mon Sep 17 00:00:00 2001 From: blackwind Date: Mon, 16 Apr 2012 07:47:49 -0600 Subject: [PATCH 5/8] Added [GetClientCount]. --- modules/modtcl.cpp | 65 +++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/modules/modtcl.cpp b/modules/modtcl.cpp index 6d5179fc..6ce8cf13 100644 --- a/modules/modtcl.cpp +++ b/modules/modtcl.cpp @@ -1,18 +1,17 @@ /* - * Copyright (C) 2004-2012 See the AUTHORS file for details. + * Copyright (C) 2004-2011 See the AUTHORS file for details. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. */ -#include -#include -#include -#include -#include -#include -#include +#include "Chan.h" +#include "IRCSock.h" +#include "Modules.h" +#include "Server.h" +#include "User.h" +#include "znc.h" #include @@ -85,11 +84,13 @@ public: Tcl_CreateCommand(interp, "Binds::ProcessNick", tcl_Bind, this, NULL); Tcl_CreateCommand(interp, "Binds::ProcessKick", tcl_Bind, this, NULL); Tcl_CreateCommand(interp, "PutIRC", tcl_PutIRC, this, NULL); + Tcl_CreateCommand(interp, "PutIRCAs", tcl_PutIRCAs, this, NULL); Tcl_CreateCommand(interp, "PutModule", tcl_PutModule, this, NULL); Tcl_CreateCommand(interp, "PutStatus", tcl_PutStatus, this, NULL); Tcl_CreateCommand(interp, "PutStatusNotice", tcl_PutStatusNotice, this, NULL); Tcl_CreateCommand(interp, "PutUser", tcl_PutUser, this, NULL); + Tcl_CreateCommand(interp, "GetLocalIP", tcl_GetLocalIP, this, NULL); Tcl_CreateCommand(interp, "GetCurNick", tcl_GetCurNick, this, NULL); Tcl_CreateCommand(interp, "GetUsername", tcl_GetUsername, this, NULL); Tcl_CreateCommand(interp, "GetRealName", tcl_GetRealName, this, NULL); @@ -101,6 +102,7 @@ public: Tcl_CreateCommand(interp, "GetServer", tcl_GetServer, this, NULL); Tcl_CreateCommand(interp, "GetServerOnline", tcl_GetServerOnline, this, NULL); Tcl_CreateCommand(interp, "GetModules", tcl_GetModules, this, NULL); + Tcl_CreateCommand(interp, "GetClientCount", tcl_GetClientCount, this, NULL); Tcl_CreateCommand(interp, "exit", tcl_exit, this, NULL); @@ -250,9 +252,15 @@ private: // Placeholder for binds incase binds.tcl isn't used static int tcl_Bind STDVAR {return TCL_OK;} + static int tcl_GetLocalIP STDVAR { + CModTcl *mod = static_cast(cd); + Tcl_SetResult(irp, (char *)mod->m_pUser->GetLocalIP().c_str(), TCL_VOLATILE); + return TCL_OK; + } + static int tcl_GetCurNick STDVAR { CModTcl *mod = static_cast(cd); - Tcl_SetResult(irp, (char *)mod->m_pNetwork->GetCurNick().c_str(), TCL_VOLATILE); + Tcl_SetResult(irp, (char *)mod->m_pUser->GetCurNick().c_str(), TCL_VOLATILE); return TCL_OK; } @@ -281,7 +289,7 @@ private: BADARGS(1, 1, ""); - const vector& Channels = mod->m_pNetwork->GetChans(); + const vector& Channels = mod->m_pUser->GetChans(); for (unsigned int c = 0; c < Channels.size(); c++) { CChan* pChan = Channels[c]; l[0] = pChan->GetName().c_str(); @@ -301,7 +309,7 @@ private: BADARGS(2, 999, " channel"); CString sChannel = argvit(argv, argc, 1, " "); - CChan *pChannel = mod->m_pNetwork->FindChan(sChannel); + CChan *pChannel = mod->m_pUser->FindChan(sChannel); if (!pChannel) { CString sMsg = "invalid channel: " + sChannel; @@ -330,7 +338,7 @@ private: BADARGS(2, 999, " channel"); CString sChannel = argvit(argv, argc, 1, " "); - CChan *pChannel = mod->m_pNetwork->FindChan(sChannel); + CChan *pChannel = mod->m_pUser->FindChan(sChannel); CString sMsg; if (!pChannel) { @@ -346,7 +354,7 @@ private: static int tcl_GetServer STDVAR { CModTcl *mod = static_cast(cd); - CServer* pServer = mod->m_pNetwork->GetCurrentServer(); + CServer* pServer = mod->m_pUser->GetCurrentServer(); CString sMsg; if (pServer) sMsg = pServer->GetName() + ":" + CString(pServer->GetPort()); @@ -356,7 +364,7 @@ private: static int tcl_GetServerOnline STDVAR { CModTcl *mod = static_cast(cd); - CIRCSock* pIRCSock = mod->m_pNetwork->GetIRCSock(); + CIRCSock* pIRCSock = mod->m_pUser->GetIRCSock(); CString sMsg = "0"; if (pIRCSock) sMsg = CString(pIRCSock->GetStartTime()); @@ -394,13 +402,36 @@ private: return TCL_OK; } + static int tcl_GetClientCount STDVAR { + CModTcl *mod = static_cast(cd); + Tcl_SetResult(irp, (char *)CString(mod->m_pUser->GetClients().size()).c_str(), TCL_VOLATILE); + return TCL_OK; + } + static int tcl_PutIRC STDVAR { CString sMsg; CModTcl *mod = static_cast(cd); BADARGS(2, 999, " string"); sMsg = argvit(argv, argc, 1, " "); - mod->m_pNetwork->PutIRC(sMsg); + mod->m_pUser->PutIRC(sMsg); + return TCL_OK; + } + + static int tcl_PutIRCAs STDVAR { + CString sMsg; + + BADARGS(3, 999, " user string"); + + CUser *pUser = CZNC::Get().FindUser(argv[1]); + if (!pUser) { + sMsg = "invalid user " + CString(argv[1]); + Tcl_SetResult(irp, (char*)sMsg.c_str(), TCL_VOLATILE); + return TCL_ERROR; + } + + sMsg = argvit(argv, argc, 2, " "); + pUser->PutIRC(sMsg); return TCL_OK; } @@ -486,8 +517,6 @@ void CModTclStartTimer::RunJob() { template<> void TModInfo(CModInfo& Info) { Info.SetWikiPage("modtcl"); - Info.SetHasArgs(true); - Info.SetArgsHelpText("The argument is the number of seconds to wait before rejoining."); } -NETWORKMODULEDEFS(CModTcl, "Loads Tcl scripts as ZNC modules") +MODULEDEFS(CModTcl, "Loads Tcl scripts as ZNC modules") From 4f942134f81602f87982e0ef087cfabdee6ded6c Mon Sep 17 00:00:00 2001 From: blackwind Date: Mon, 16 Apr 2012 07:50:22 -0600 Subject: [PATCH 6/8] Added [GetClientCount]. Correct file this time. --- modules/modtcl.cpp | 58 ++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/modules/modtcl.cpp b/modules/modtcl.cpp index 6ce8cf13..3eac6e97 100644 --- a/modules/modtcl.cpp +++ b/modules/modtcl.cpp @@ -1,17 +1,18 @@ /* - * Copyright (C) 2004-2011 See the AUTHORS file for details. + * Copyright (C) 2004-2012 See the AUTHORS file for details. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. */ -#include "Chan.h" -#include "IRCSock.h" -#include "Modules.h" -#include "Server.h" -#include "User.h" -#include "znc.h" +#include +#include +#include +#include +#include +#include +#include #include @@ -84,13 +85,11 @@ public: Tcl_CreateCommand(interp, "Binds::ProcessNick", tcl_Bind, this, NULL); Tcl_CreateCommand(interp, "Binds::ProcessKick", tcl_Bind, this, NULL); Tcl_CreateCommand(interp, "PutIRC", tcl_PutIRC, this, NULL); - Tcl_CreateCommand(interp, "PutIRCAs", tcl_PutIRCAs, this, NULL); Tcl_CreateCommand(interp, "PutModule", tcl_PutModule, this, NULL); Tcl_CreateCommand(interp, "PutStatus", tcl_PutStatus, this, NULL); Tcl_CreateCommand(interp, "PutStatusNotice", tcl_PutStatusNotice, this, NULL); Tcl_CreateCommand(interp, "PutUser", tcl_PutUser, this, NULL); - Tcl_CreateCommand(interp, "GetLocalIP", tcl_GetLocalIP, this, NULL); Tcl_CreateCommand(interp, "GetCurNick", tcl_GetCurNick, this, NULL); Tcl_CreateCommand(interp, "GetUsername", tcl_GetUsername, this, NULL); Tcl_CreateCommand(interp, "GetRealName", tcl_GetRealName, this, NULL); @@ -252,15 +251,9 @@ private: // Placeholder for binds incase binds.tcl isn't used static int tcl_Bind STDVAR {return TCL_OK;} - static int tcl_GetLocalIP STDVAR { - CModTcl *mod = static_cast(cd); - Tcl_SetResult(irp, (char *)mod->m_pUser->GetLocalIP().c_str(), TCL_VOLATILE); - return TCL_OK; - } - static int tcl_GetCurNick STDVAR { CModTcl *mod = static_cast(cd); - Tcl_SetResult(irp, (char *)mod->m_pUser->GetCurNick().c_str(), TCL_VOLATILE); + Tcl_SetResult(irp, (char *)mod->m_pNetwork->GetCurNick().c_str(), TCL_VOLATILE); return TCL_OK; } @@ -289,7 +282,7 @@ private: BADARGS(1, 1, ""); - const vector& Channels = mod->m_pUser->GetChans(); + const vector& Channels = mod->m_pNetwork->GetChans(); for (unsigned int c = 0; c < Channels.size(); c++) { CChan* pChan = Channels[c]; l[0] = pChan->GetName().c_str(); @@ -309,7 +302,7 @@ private: BADARGS(2, 999, " channel"); CString sChannel = argvit(argv, argc, 1, " "); - CChan *pChannel = mod->m_pUser->FindChan(sChannel); + CChan *pChannel = mod->m_pNetwork->FindChan(sChannel); if (!pChannel) { CString sMsg = "invalid channel: " + sChannel; @@ -338,7 +331,7 @@ private: BADARGS(2, 999, " channel"); CString sChannel = argvit(argv, argc, 1, " "); - CChan *pChannel = mod->m_pUser->FindChan(sChannel); + CChan *pChannel = mod->m_pNetwork->FindChan(sChannel); CString sMsg; if (!pChannel) { @@ -354,7 +347,7 @@ private: static int tcl_GetServer STDVAR { CModTcl *mod = static_cast(cd); - CServer* pServer = mod->m_pUser->GetCurrentServer(); + CServer* pServer = mod->m_pNetwork->GetCurrentServer(); CString sMsg; if (pServer) sMsg = pServer->GetName() + ":" + CString(pServer->GetPort()); @@ -364,7 +357,7 @@ private: static int tcl_GetServerOnline STDVAR { CModTcl *mod = static_cast(cd); - CIRCSock* pIRCSock = mod->m_pUser->GetIRCSock(); + CIRCSock* pIRCSock = mod->m_pNetwork->GetIRCSock(); CString sMsg = "0"; if (pIRCSock) sMsg = CString(pIRCSock->GetStartTime()); @@ -414,24 +407,7 @@ private: BADARGS(2, 999, " string"); sMsg = argvit(argv, argc, 1, " "); - mod->m_pUser->PutIRC(sMsg); - return TCL_OK; - } - - static int tcl_PutIRCAs STDVAR { - CString sMsg; - - BADARGS(3, 999, " user string"); - - CUser *pUser = CZNC::Get().FindUser(argv[1]); - if (!pUser) { - sMsg = "invalid user " + CString(argv[1]); - Tcl_SetResult(irp, (char*)sMsg.c_str(), TCL_VOLATILE); - return TCL_ERROR; - } - - sMsg = argvit(argv, argc, 2, " "); - pUser->PutIRC(sMsg); + mod->m_pNetwork->PutIRC(sMsg); return TCL_OK; } @@ -517,6 +493,8 @@ void CModTclStartTimer::RunJob() { template<> void TModInfo(CModInfo& Info) { Info.SetWikiPage("modtcl"); + Info.SetHasArgs(true); + Info.SetArgsHelpText("The argument is the number of seconds to wait before rejoining."); } -MODULEDEFS(CModTcl, "Loads Tcl scripts as ZNC modules") +NETWORKMODULEDEFS(CModTcl, "Loads Tcl scripts as ZNC modules") From 4786b743cd847b10b17db6ea40deb2ede104f5d6 Mon Sep 17 00:00:00 2001 From: blackwind Date: Wed, 18 Apr 2012 04:11:03 -0600 Subject: [PATCH 7/8] Updated [ProcessKick] to eggdrop spec, removed bind types that weren't actually supported, and removed default variable for [::bind], as this served no purpose. --- modules/modtcl/binds.tcl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/modtcl/binds.tcl b/modules/modtcl/binds.tcl index a55cc5c6..f7cc6aaa 100644 --- a/modules/modtcl/binds.tcl +++ b/modules/modtcl/binds.tcl @@ -6,7 +6,7 @@ # # Binds module to process incoming messages with ZNC modtcl # -# Supported bind types: pub/pubm, msg/msgm, time, evnt, nick, bot, dcc, kick +# Supported bind types: bot, dcc, evnt, kick, msg, msgm, nick, pub, pubm, time # evnt: prerehash,rehash,init-server,disconnect-server # @@ -19,15 +19,11 @@ namespace eval Binds { # procs proc Add {type flags cmd {procname ""}} { - if {![regexp {^(pub|pubm|msg|msgm|nick|mode|raw|bot|time|evnt|dcc|kick)$} $type]} { + if {![regexp {^(bot|dcc|evnt|kick|msg|msgm|nick|pub|pubm|time)$} $type]} { PutModule "Tcl error: Bind type: $type not supported" return } # ToDo: Flags check from user info (IsAdmin, etc) - if {$procname == ""} { - PutModule "Tcl error: Without a proc binds are useless" - return - } # ToDo: bind hit counter if {[lsearch $Binds::List "$type $flags [list $cmd] 0 [list $procname]"] == -1} { lappend Binds::List "$type $flags [list $cmd] 0 [list $procname]" @@ -127,8 +123,12 @@ namespace eval Binds { proc ProcessKick {nick user handle channel target reason} { foreach n [binds kick] { - if {[string match [lindex $n 2 0] $channel] && [string match [lindex $n 2 1] $target]} { - [lindex $n 4] $nick $user $handle $channel $target $reason + if {[string match [lindex $n 2 0] $channel]} { + if {[llength [lindex $n 2]] <= 1 || [string match [lindex $n 2 1] $target]} { + if {[llength [lindex $n 2]] <= 2 || [string match [lindex $n 2 2] $reason]} { + [lindex $n 4] $nick $user $handle $channel $target $reason + } + } } } } @@ -148,7 +148,7 @@ namespace eval Binds { } # Provide aliases according to eggdrop specs -proc ::bind {type flags cmd {procname ""}} {Binds::Add $type $flags $cmd $procname} +proc ::bind {type flags cmd procname} {Binds::Add $type $flags $cmd $procname} proc ::unbind {type flags cmd procname} {Binds::Del $type $flags $cmd $procname} proc ::binds {{type ""}} {if {$type != ""} {set type "$type "};return [lsearch -all -inline $Binds::List "$type*"]} proc ::bindlist {{type ""}} {foreach bind $Binds::List {PutModule "$bind"}} From 1da11b0b2b002c8ef3428761f90bbb8a9853a093 Mon Sep 17 00:00:00 2001 From: blackwind Date: Wed, 18 Apr 2012 09:43:44 -0600 Subject: [PATCH 8/8] Fixed [GetClientCount]. --- modules/modtcl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/modtcl.cpp b/modules/modtcl.cpp index 3eac6e97..3ef27615 100644 --- a/modules/modtcl.cpp +++ b/modules/modtcl.cpp @@ -397,7 +397,7 @@ private: static int tcl_GetClientCount STDVAR { CModTcl *mod = static_cast(cd); - Tcl_SetResult(irp, (char *)CString(mod->m_pUser->GetClients().size()).c_str(), TCL_VOLATILE); + Tcl_SetResult(irp, (char *)CString(mod->m_pNetwork->GetClients().size()).c_str(), TCL_VOLATILE); return TCL_OK; }