Attribute VB_Name = "modVar"
Type Admin
Name As String
Email As String
Location As String
End Type
Type Channel
Title As String
Topic As String
TopicTime As Long
TopicUser As String
Modes As String
Bans(0 To 1000) As String
UMode(0 To 1000) As String
Created As Long
Key As String
ULimit As Integer
IndexDB As Integer
End Type
Type Client
Nick As String
User As String
Host As String
Modes As String
State As Integer
LastPing As Long
GotPong As Long
Chans(1 To 1000) As Integer
Invite(1 To 1000) As Integer
RealName As String
ConnectTime As Long
LastAction As Long
Pass As String
NickTimer As Long
NickMatch As Integer
IsAway As Byte
AwayMsg As String
End Type
Type Oper
Name As String
Host As String
Password As String
Modes As String
End Type
Type SvcServer
Host As String
Name As String
Password As String
Desc As String
End Type
Type RemoteType
Host As String
User As String
Password As String
End Type
Public SQct As Integer
Public Services As SvcServer
Public SvcSock As Integer
Public Creation As String
Public WorkDir As String
Public Sysop As Admin
Public ServerHost As String
Public ServerName As String
Public ServType As Integer
Public Remote As RemoteType
Public Clients(0 To 1000) As Client
Public Chans(0 To 1000) As Channel
Public Opers(1 To 1000) As Oper
Public Buffer(0 To 1000) As String
Public InBuffer(0 To 1000) As String
Public Reserved(1 To 100) As String
Public lPort As Integer
Public MOTD As String
Public KillFlag(0 To 1000) As Byte
Public Temp(0 To 1000) As Byte
Public OperCt As Integer
Public Hash As New MD5
Public NickLen As Byte
Public ChanLen As Byte
Public TopicLen As Integer
Public PingInterval As Integer
Public PingTimeout As Integer
Public Const NickChars As String = "0123456789qwertyuiop[]|\asdfghjkl;'zxcvbnm./^-_"
Public Const ChanChars As String = "#0123456789qwertyuiop[]|\asdfghjkl;'zxcvbnm./^-_"
Public Const Build As String = "tsIRCd 1.2"
Public Sub InitServer()
Creation = Date$ + " " + Time$
WorkDir = ""
NickLen = 32
ChanLen = 32
TopicLen = 400
PingInterval = 120
PingTimeout = 60
NS.AutoProtect = 1
NS.GuestPrefix = "Guest"
RehashMOTD
RehashConfig
For n = frmMain.Sock.lbound To frmMain.Sock.UBound
frmMain.Sock(n).Close
Next n
curunix& = UnixTimeEnc&(Date$, Timer)
For n = frmMain.sckListen.lbound To frmMain.sckListen.UBound
frmMain.sckListen(n).Close
frmMain.sckListen(n).LocalPort = lPort
'On Error Resume Next
frmMain.sckListen(n).Listen
Clients(n).LastPing = curunix&
Next n
InitServices
frmMain.PingTimer.Interval = 1000
frmMain.PingTimer.Enabled = True
End Sub
Public Sub RehashConfig()
Dim args(10) As String
nf = FreeFile
Open WorkDir + "tsIRCd.config" For Input As nf
For n = 1 To 1000
Opers(n).Host = ""
Opers(n).Modes = ""
Opers(n).Name = ""
Opers(n).Password = ""
Next n
OperCt = 1
Do Until EOF(nf)
Line Input #nf, tmp$
tmp$ = LTrim$(tmp$)
If Left$(tmp$, 1) <> "#" Then
carg = 0
Do Until Len(tmp$) = 0
xp = InStr(1, tmp$, ":")
If xp < 1 Then xp = Len(tmp$) + 1
args(carg) = Left$(tmp$, xp - 1)
tmp$ = Mid$(tmp$, xp + 1)
carg = carg + 1
Loop
Select Case LCase$(args(0))
Case "d"
ServerName = args(1)
Case "m"
ServerHost = args(1)
Case "a"
Sysop.Name = args(1)
Sysop.Email = args(2)
Case "r"
Remote.Host = args(1)
Remote.Password = args(2)
Remote.User = args(3)
Case "o"
If Len(args(1)) > 0 Then
Opers(OperCt).Host = args(1)
Opers(OperCt).Password = args(2)
Opers(OperCt).Name = args(3)
Opers(OperCt).Modes = args(5)
OperCt = OperCt + 1
End If
Case "p"
lPort = Val(args(4))
Case "s"
Select Case LCase$(args(1))
Case "none"
ServType = 0
Case "internal"
ServType = 1
Case Else
ServType = 2
Services.Host = args(1)
Services.Password = args(2)
Services.Name = args(3)
End Select
Case "ns"
Select Case LCase$(args(1))
Case "autoprotect"
NS.AutoProtect = Val(args(2))
Case "guestprefix"
NS.GuestPrefix = args(2)
End Select
End Select
'carg = carg + 1
'Loop
End If
Loop
Close nf
frmMain.MaintTimer.Enabled = True
End Sub
Public Sub SM(Recipient As Integer, Message As String)
'If Recipient = SvcSock And frmMain.chkDebug.value = vbChecked Then frmMain.txtDebug = frmMain.txtDebug + "---> " + Message + vbCrLf: frmMain.txtDebug.SelStart = Len(frmMain.txtDebug) + 1
If Len(LTrim$(RTrim$(Message))) = 0 Then Exit Sub
origsize = Len(Buffer(Recipient))
Buffer(Recipient) = Buffer(Recipient) + Message + Chr$(13)
xp = InStr(1, Buffer(Recipient), Chr$(13))
If xp < 1 Then xp = Len(Buffer(Recipient)) + 1
a$ = Left$(Buffer(Recipient), xp - 1)
Buffer(Recipient) = Mid$(Buffer(Recipient), xp + 1)
If Recipient > frmMain.Sock.UBound Then Exit Sub
If origsize = 0 Then 'And frmMain.Sock(Recipient).State = sckConnected Then
On Error Resume Next: frmMain.Sock(Recipient).SendData a$ + vbCrLf: On Error GoTo 0
If frmMain.Visible = True Then
frmMain.Text1 = frmMain.Text1 + "--->" + a$ + vbCrLf
frmMain.Text1.SelStart = Len(frmMain.Text1) + 1
End If
End If
End Sub
Public Sub ClearClientSlot(SockVal As Integer)
frmMain.Sock(SockVal).Close
Clients(SockVal).Host = ""
Clients(SockVal).Modes = ""
Clients(SockVal).Nick = ""
Clients(SockVal).State = 0
Clients(SockVal).User = ""
Clients(SockVal).LastPing = 0
Clients(SockVal).GotPong = 0
Clients(SockVal).RealName = ""
Clients(SockVal).LastAction = 0
Clients(SockVal).ConnectTime = 0
Clients(SockVal).Pass = ""
Clients(SockVal).NickTimer = 0
Clients(SockVal).IsAway = 0
Clients(SockVal).AwayMsg = ""
For n = 1 To 1000
If Clients(SockVal).Chans(n) = 1 Then Chans(n).UMode(SockVal) = ""
Clients(SockVal).Chans(n) = 0
Clients(SockVal).Invite(n) = 0
Next n
Buffer(SockVal) = ""
KillFlag(SockVal) = 0
End Sub
Public Function ReplaceAll$(NewString As String, LookFor As String, ReplaceWith As String)
Dim NS As String
NS = NewString
Do
xp = InStr(1, NS, LookFor)
If xp < 1 Then Exit Do
NS = Left$(NS, xp - 1) + ReplaceWith + Mid$(NS, xp + Len(ReplaceWith))
Loop Until Not InStr(1, NS, LookFor)
ReplaceAll$ = NS
End Function
Public Sub ProcessInput(FromSock As Integer, InData As String)
If Len(InData) = 0 Then Exit Sub
Dim newchan As Integer
Dim args(20) As String
tmpd$ = LTrim$(InData)
Select Case UCase$(Left$(tmpd$, 3))
Case "NS "
tmpd$ = "PRIVMSG NickServ " + Mid$(tmpd$, 4)
Case "CS "
tmpd$ = "PRIVMSG ChanServ " + Mid$(tmpd$, 4)
Case "OS "
tmpd$ = "PRIVMSG OperServ " + Mid$(tmpd$, 4)
Case "HS "
tmpd$ = "PRIVMSG HostServ " + Mid$(tmpd$, 4)
Case "MS "
tmpd$ = "PRIVMSG MemoServ " + Mid$(tmpd$, 4)
End Select
Select Case UCase$(Left$(tmpd$, 9))
Case "NICKSERV "
tmpd$ = "PRIVMSG NickServ " + Mid$(tmpd$, 10)
Case "CHANSERV "
tmpd$ = "PRIVMSG ChanServ " + Mid$(tmpd$, 10)
Case "OPERSERV "
tmpd$ = "PRIVMSG OperServ " + Mid$(tmpd$, 10)
Case "HOSTSERV "
tmpd$ = "PRIVMSG HostServ " + Mid$(tmpd$, 10)
Case "MEMOSERV "
tmpd$ = "PRIVMSG MemoServ " + Mid$(tmpd$, 10)
End Select
'tmpd$ = ReplaceAll$(tmpd$, Chr$(13), "")
'tmpd$ = ReplaceAll$(tmpd$, Chr$(10), "")
fullline$ = tmpd$
If frmMain.Visible = True Then
frmMain.Text1 = frmMain.Text1 + "<---" + fullline$ + vbCrLf
frmMain.Text1.SelStart = Len(frmMain.Text1) + 1
End If
xp = InStr(1, tmpd$, " ")
If xp < 1 Then xp = Len(tmpd$) + 1
args(0) = UCase$(Left$(tmpd$, xp - 1))
tmpd$ = LTrim$(Mid$(tmpd$, xp + 1))
origline$ = tmpd$
carg = 1
Do
xp = InStr(1, tmpd$, " ")
If xp < 1 Then args(carg) = tmpd$: Exit Do
args(carg) = Left$(tmpd$, xp - 1)
tmpd$ = LTrim$(Mid$(tmpd$, xp + 1))
carg = carg + 1
Loop Until carg = 21
If UCase$(args(1)) = "PONG" Then args(0) = args(1): args(1) = args(2)
If UCase$(args(0)) <> "PONG" Then Clients(FromSock).LastAction = UnixTimeEnc&(Date$, Timer)
'If Clients(FromSock).State = 2 Then
'
'End If
If Clients(FromSock).State = 0 Then
Select Case args(0)
Case "NICK"
args(1) = NormalizeNick(args(1))
If NickInUse(args(1)) Then
SendError FromSock, 433, args(1) + " :Nickname is already in use"
Else
If Len(args(1)) > 0 Then
Clients(FromSock).Nick = args(1)
Clients(FromSock).NickMatch = 0
If IsUserMode(FromSock, "r") Then UnSetUserMode FromSock, ServerHost, "r"
Else
SendError FromSock, 431, ":No nickname given"
End If
End If
Case "USER"
If Len(args(1)) = 0 Then
SendError FromSock, 461, args(0) + " :Not enough parameters"
Else
Clients(FromSock).User = args(1)
xp = InStr(1, origline$, ":")
If xp > 0 Then Clients(FromSock).RealName = Mid$(origline$, xp + 1) Else Clients(FromSock).RealName = "Nobody"
End If
Case "PASS"
If Len(args(1)) > 0 Then
If Left$(args(1), 1) = ":" Then args(1) = Mid$(args(1), 2)
Clients(FromSock).Pass = Hash.DigestStrToHexStr(args(1))
Else
SendError FromSock, 461, args(0) + " :Not enough parameters"
End If
Case "REMOTE"
If LCase$(args(2)) = Hash.DigestStrToHexStr(Clients(FromSock).Pass) Then
End If
'Case "SERIVCES"
'if lcase$(args(1)) = lcase$(services.host) then
Case "PONG"
Clients(FromSock).GotPong = 1
Case Else
If Len(args(0)) > 0 Then SendError FromSock, 451, ":You have not registered " + args(0) + " " + origline$
End Select
If Len(Clients(FromSock).Nick) > 0 And Len(Clients(FromSock).User) > 0 Then SendGreeting FromSock: Clients(FromSock).State = 1
Exit Sub
End If
Select Case args(0)
Case "MOTD"
SendMOTD FromSock
Case "USER"
SendError FromSock, 462, ":You may not reregister"
Case "WHO"
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
args(1) = LTrim$(RTrim$(args(1)))
args(2) = LTrim$(RTrim$(args(2)))
If LCase$(args(2)) = "o" Then filteroper = 1 Else filteroper = 0
If Left$(args(1), 1) = "#" Then
newchan = ChanExists(args(1))
If newchan > 0 Then
For n = 0 To frmMain.Sock.UBound
If n > frmMain.Sock.UBound Then Exit For
If Clients(n).Chans(newchan) = 1 Then
If Clients(n).IsAway = 0 Then prefix$ = "H" Else prefix$ = "G"
If IsUserMode(Int(n), "ao") Then prefix$ = prefix$ + "*"
If IsUserChanMode(Int(n), newchan, "v") Then prefix$ = prefix$ + "+"
If IsUserChanMode(Int(n), newchan, "o") Then prefix$ = prefix$ + "@"
If IsUserChanMode(Int(n), newchan, "q") Then prefix$ = prefix$ + "~"
If filteropers = 0 Then
SM FromSock, ":" + ServerHost + " 352 " + Clients(FromSock).Nick + " " + args(1) + " " + Clients(n).User + " " + Clients(n).Host + " " + ServerHost + " " + Clients(n).Nick + " " + prefix$ + " :0 " + Clients(n).RealName
Else
If IsUserMode(Int(n), "ao") Then SM FromSock, ":" + ServerHost + " 352 " + Clients(FromSock).Nick + " " + args(1) + " " + Clients(n).User + " " + Clients(n).Host + " " + ServerHost + " " + Clients(n).Nick + " " + prefix$ + " :0 " + Clients(n).RealName
End If
End If
Next n
Else
For n = 0 To frmMain.Sock.UBound
If n > frmMain.Sock.UBound Then Exit For
If Len(Clients(n).Nick) > 0 Then
If Clients(n).IsAway = 0 Then prefix$ = "H" Else prefix$ = "G"
If IsUserMode(Int(n), "ao") Then prefix$ = prefix$ + "*"
If filteropers = 0 Then
If IsUserMode(Int(n), "i") = 0 Then SM FromSock, ":" + ServerHost + " 352 " + Clients(FromSock).Nick + " * " + Clients(n).User + " " + Clients(n).Host + " " + ServerHost + " " + Clients(n).Nick + " " + prefix$ + " :0 " + Clients(n).RealName
Else
If IsUserMode(Int(n), "ao") <> 0 And IsUserMode(Int(n), "i") = 0 Then SM FromSock, ":" + ServerHost + " 352 " + Clients(FromSock).Nick + " * " + Clients(n).User + " " + Clients(n).Host + " " + ServerHost + " " + Clients(n).Nick + " " + prefix$ + " :0 " + Clients(n).RealName
End If
End If
Next n
End If
End If
SM FromSock, ":" + ServerHost + " 315 " + Clients(FromSock).Nick + " " + args(1) + " :End of /WHO list."
Case "PART"
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
xp = InStr(1, origline$, " ")
If xp > 0 Then
partreason$ = Mid$(origline$, xp + 1)
origline$ = Left$(origline$, xp - 1)
Else
partreason$ = ""
End If
Do Until Len(origline$) = 0
xp = InStr(1, origline$, ",")
If xp < 1 Then xp = Len(origline$) + 1
cc$ = Left$(origline$, xp - 1)
origline$ = Mid$(origline$, xp + 1)
cc$ = NormalizeChan$(cc$)
If Len(cc$) < 2 Then
SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
Else
newchan = ChanExists(cc$)
If newchan > 0 Then
If Clients(FromSock).Chans(newchan) = 1 Then
PartChan FromSock, newchan, partreason$
Else
SendError FromSock, 442, cc$ + " :You're not on that channel"
End If
Else
SendError FromSock, 403, cc$ + " :No such channel"
End If
End If
Loop
Case "JOIN"
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
Do Until Len(origline$) = 0
xp = InStr(1, origline$, ",")
If xp < 1 Then xp = Len(origline$) + 1
cc$ = Left$(origline$, xp - 1)
origline$ = Mid$(origline$, xp + 1)
xp = InStr(1, cc$, " ")
If xp < 1 Then ckey$ = "" Else ckey$ = Mid$(cc$, xp + 1): cc$ = Left$(cc$, xp - 1)
cc$ = NormalizeChan$(cc$)
If Len(cc$) < 2 Then
SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
Else
If Left$(cc$, 1) = "#" Then
newchan = JoinChan(FromSock, cc$, ckey$)
Else
SendError FromSock, 401, cc$ + " :No such nick/channel"
End If
End If
Loop
'If Chans(newchan).IndexDB > 0 Then ChanMaint newchan
Case "OPER"
For n = 1 To OperCt
If LCase$(args(1)) = LCase$(Opers(n).Name) And Hash.DigestStrToHexStr(args(2)) = Opers(n).Password And MatchMask%(Clients(FromSock).Host, Opers(n).Host) = 1 Then
SetUserMode FromSock, ServerHost, Opers(n).Modes
SM FromSock, ":" + ServerHost + " 381 " + Clients(FromSock).Nick + " :You are now an e-god. Play nicely with the other children."
SM FromSock, ":" + ServerHost + " NOTICE " + Clients(FromSock).Nick + " :*** Oper priveleges are " + Opers(n).Modes
Exit Sub
End If
Next n
SM FromSock, ":" + ServerHost + " 491 " + Clients(FromSock).Nick + " :There is no O-line for your host."
Case "PRIVMSG", "NOTICE"
If IsRsvd(args(1)) = 1 Then
HandleServiceMsg FromSock, args(1), Mid$(origline$, Len(args(1)) + 1)
Exit Sub
End If
'SM SvcSock, ":" + Clients(FromSock).Nick + " " + args(0) + " " + args(1) + " " + Mid$(origline$, Len(args(1)) + 1): Exit Sub
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
If Len(args(2)) = 0 Then SendError FromSock, 412, ":No text to send": Exit Sub
cansend = 1
If Left$(args(1), 1) = "#" Then
newchan = ChanExists(args(1))
If newchan = 0 Then
SendError FromSock, 401, cc$ + " :No such nick/channel"
Else
If IsChanMode(newchan, "n") = 1 And Clients(FromSock).Chans(newchan) = 0 Then
SendError FromSock, 404, Chans(newchan).Title + " :Cannot send to channel (+n)"
cansend = 0
Else
If IsUserChanMode(FromSock, newchan, "qov") = 0 And IsChanMode(newchan, "m") = 1 Then
SendError FromSock, 404, Chans(newchan).Title + " :Cannot send to channel (+m)"
cansend = 0
End If
End If
End If
For n = 0 To 1000
If Len(Chans(newchan).Bans(n)) > 0 Then
If MatchMask%(FullHost(FromSock), Chans(newchan).Bans(n)) = 1 And IsUserChanMode(FromSock, newchan, "qo") = 0 Then
If IsUserMode(FromSock, "ao") Then cansend = 1: Exit For
SendError FromSock, 404, Chans(newchan).Title + " :Cannot send to channel (+b)"
cansend = 0
Exit For
End If
End If
Next n
If cansend = 1 Then BroadcastChan newchan, ":" + FullHost(FromSock) + " " + args(0) + " " + Chans(newchan).Title + Mid$(origline$, Len(args(1)) + 1), FromSock
Else
tmpub = frmMain.Sock.UBound
For n = 0 To tmpub
If LCase$(Clients(n).Nick) = LCase$(args(1)) Then
SM Int(n), ":" + FullHost(FromSock) + " " + args(0) + " " + Clients(n).Nick + Mid$(origline$, Len(args(1)) + 1)
If Clients(n).IsAway = 1 Then SM Int(n), ":" + ServerHost + " 301 " + Clients(FromSock).Nick + " " + Clients(n).Nick + " " + Clients(n).AwayMsg
Exit For
End If
Next n
If n > tmpub Then SendError FromSock, 401, args(1) + " :No such nick/channel"
End If
Case "NICK"
args(1) = NormalizeNick(args(1))
If NickInUse(args(1)) Then
SendError FromSock, 433, args(1) + " :Nickname is already in use"
Else
If Len(args(1)) > 0 Then
Clients(FromSock).NickMatch = 0
ChangeNick FromSock, args(1)
If ServType = 1 Then
If IsUserMode(FromSock, "r") Then UnSetUserMode FromSock, ServerHost, "r"
NickCheck FromSock, Clients(FromSock).Nick
End If
Else
SendError FromSock, 431, ":No nickname given"
End If
End If
Case "NAMES"
If Len(args(1)) > 0 Then
Do Until Len(origline$) = 0
xp = InStr(1, origline$, ",")
If xp < 1 Then xp = Len(origline$) + 1
cc$ = Left$(origline$, xp - 1)
origline$ = Mid$(origline$, xp + 1)
canview% = ChanExists(cc$)
If canview% > 0 Then
If Clients(FromSock).Chans(canview%) = 0 Then
If IsChanMode(canview%, "ps") Then canview% = 0
End If
End If
If canview% > 0 Then SendNames FromSock, canview%
Loop
Else
'code for seeings all users on all channels goes here. but EWWW, massive CPU usage right thar.
End If
SM FromSock, ":" + ServerHost + " 366 " + Clients(SockVal).Nick + " :End of /NAMES list"
Case "USERHOST"
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
whichuser% = FindClient(args(1))
If whichuser% = -1 Then SendError FromSock, 401, args(1) + " :No such nick/channel": Exit Sub
SM FromSock, ":" + ServerHost + " 302 " + Clients(FromSock).Nick + " :" + Clients(whichuser%).Nick + "=+" + Clients(whichuser%).User + "@" + Clients(whichuser%).Host
Case "MODE"
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
If Left$(args(1), 1) = "#" Then
newchan = ChanExists(args(1))
If newchan = 0 Then
SendError FromSock, 403, args(1) + " :No such channel"
Else
'MsgBox args(2)
If Len(args(2)) < 2 Then 'requesting chan's modes
extra$ = ""
If IsUserMode(FromSock, "ao") = 1 Or IsUserChanMode(FromSock, newchan, "qo") = 1 Then
For n = 1 To Len(Chans(newchan).Modes)
Select Case Mid$(Chans(newchan).Modes, n, 1)
Case "l"
extra$ = extra$ + Str$(Chans(newchan).ULimit)
End Select
Next n
End If
SM FromSock, ":" + ServerHost + " 324 " + Clients(FromSock).Nick + " " + Chans(newchan).Title + " +" + Chans(newchan).Modes + extra$
SM FromSock, ":" + ServerHost + " 329 " + Clients(FromSock).Nick + " " + Chans(newchan).Title + Str$(Chans(newchan).Created)
Else
curop$ = Left$(args(2), 1)
If curop$ <> "+" And curop$ <> "-" Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
carg = 3
For n = 1 To Len(args(2))
'If Len(args(carg)) = 0 Then Exit For
cc$ = Mid$(args(2), n, 1)
If cc$ <> "b" And IsUserMode(FromSock, "ao") = 0 And IsUserChanMode(FromSock, newchan, "qo") = 0 Then SendError FromSock, 482, Chans(newchan).Title + " :You're not channel operator": Exit Sub
Select Case cc$
Case "b"
If Len(args(3)) = 0 Then 'requesting chan's ban list
For nu = 0 To 1000
If Len(Chans(newchan).Bans(nu)) > 0 Then SM FromSock, ":" + ServerHost + " 367 " + Clients(FromSock).Nick + " " + Chans(newchan).Title + " " + Chans(newchan).Bans(nu)
Next nu
SM FromSock, ":" + ServerHost + " 368 " + Clients(FromSock).Nick + " " + Chans(newchan).Title + " :End of Channel Ban List"
Else
'do ban code stuffs here
If IsUserMode(FromSock, "ao") = 0 And IsUserChanMode(FromSock, newchan, "qo") = 0 Then SendError FromSock, 482, Chans(newchan).Title + " :You're not channel operator": Exit Sub
BroadcastChan newchan, ":" + FullHost(FromSock) + " MODE " + Chans(newchan).Title + " " + curop$ + "b " + args(carg), -1
For nu = 0 To 1000
If curop$ = "+" Then
If Len(Chans(newchan).Bans(nu)) = 0 Then
Chans(newchan).Bans(nu) = args(carg)
Exit For
End If
Else
If Chans(newchan).Bans(nu) = args(carg) Then
Chans(newchan).Bans(nu) = ""
Exit For
End If
End If
Next nu
carg = carg + 1
End If
'Case "q"
Case "o", "v"
newuser% = FindClient(args(carg))
If newuser% > -1 Then
If Clients(newuser%).Chans(newchan) = 0 Then
SendError FromSock, 441, Clients(newuser%).Nick + " " + Chans(newchan).Title + " :They aren't on that channel"
Else
If curop$ = "+" Then
SetUserChanMode newchan, FullHost(FromSock), newuser%, cc$
ChanMaint newchan
SendModes FromSock, newchan
Else
UnSetUserChanMode newchan, FullHost(FromSock), newuser%, cc$
ChanMaint newchan
SendModes FromSock, newchan
End If
End If
Else
SendError FromSock, 401, args(carg) + " :No such nick/channel"
End If
carg = carg + 1
Case "t", "n", "m", "p", "s", "i"
If curop$ = "+" Then
SetChanMode newchan, FullHost(FromSock), cc$
ChanMaint newchan
SendModes FromSock, newchan
Else
UnSetChanMode newchan, FullHost(FromSock), cc$
ChanMaint newchan
SendModes FromSock, newchan
End If
Case "k"
If curop$ = "+" Then
If Len(args(carg)) > 0 Then
If InStr(1, Chans(newchan).Modes, cc$) < 1 Then Chans(newchan).Modes = Chans(newchan).Modes + cc$
BroadcastChan newchan, ":" + FullHost(FromSock) + " MODE " + Chans(newchan).Title + " +k " + args(carg), -1
Chans(newchan).Key = args(carg)
End If
Else
UnSetChanMode newchan, FullHost(FromSock), cc$
ChanMaint newchan
SendModes FromSock, newchan
Chans(newchan).Key = ""
End If
carg = carg + 1
Case "l"
If curop$ = "+" Then
If Val(args(carg)) > 0 Then
If InStr(1, Chans(newchan).Modes, cc$) < 1 Then Chans(newchan).Modes = Chans(newchan).Modes + cc$
Chans(newchan).ULimit = Val(args(carg))
BroadcastChan newchan, ":" + FullHost(FromSock) + " MODE " + Chans(newchan).Title + " :+l" + Str$(Chans(newchan).ULimit), -1
ChanMaint newchan
SendModes FromSock, newchan
End If
Else
UnSetChanMode newchan, FullHost(FromSock), cc$
ChanMaint newchan
SendModes FromSock, newchan
Chans(newchan).ULimit = 0
End If
carg = carg + 1
Case "+", "-"
curop$ = cc$
Case Else
SendError FromSock, 472, cc$ + " :is unknown mode char to me"
End Select
Next n
End If
End If
Else
newuser% = FindClient(args(1))
If newuser% <> FromSock And IsUserMode(FromSock, "qo") = 0 Then SendError FromSock, 502, ":Can't change mode for other users": Exit Sub
If Len(args(2)) = 0 Then
SM FromSock, ":" + ServerHost + " 221 " + Clients(newuser%).Nick + " +" + Clients(newuser%).Modes
Else
If Len(args(1)) < 2 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
curop$ = "+"
For n = 1 To Len(args(1))
cc$ = Mid$(args(1), n, 1)
Select Case cc$
Case "+", "-"
curop$ = cc$
Case "i"
If curop$ = "+" Then
SetUserMode newuser%, FullHost(FromSock), cc$
Else
UnSetUserMode newuser%, FullHost(FromSock), cc$
End If
End Select
Next n
End If
End If
Case "TOPIC"
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
newchan = ChanExists(args(1))
If newchan = 0 Then
SendError FromSock, 401, args(1) + " :No such nick/channel"
Else
newtopic$ = Mid$(origline$, Len(args(1)) + 1)
If Len(newtopic$) = 0 Then
SendTopic FromSock, newchan
Else
If Clients(FromSock).Chans(newchan) = 0 Then SendError FromSock, 442, Chans(newchan).Title + " :You're not on that channel": Exit Sub
If IsChanMode(newchan, "t") <> 0 And IsUserChanMode(FromSock, newchan, "qo") = 0 Then
SendError FromSock, 482, Chans(newchan).Title + " :You're not channel operator (+t is set)"
Exit Sub
End If
BroadcastChan newchan, ":" + FullHost(FromSock) + " TOPIC " + Chans(newchan).Title + newtopic$, -1
Chans(newchan).Topic = newtopic$
Chans(newchan).TopicTime = UnixTimeEnc&(Date$, Timer)
Chans(newchan).TopicUser = Clients(FromSock).Nick
IndexDB = IsChanReg(Chans(newchan).Title)
If IndexDB > 0 Then
ChanDB(IndexDB).Topic = newtopic$
ChanDB(IndexDB).TopicUser = Clients(FromSock).Nick
ChanDB(IndexDB).TopicTime = Chans(newchan).TopicTime
ServMaint
End If
End If
End If
Case "WHOIS"
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
Do
xp = InStr(1, args(1), ",")
If xp < 1 Then xp = Len(args(1)) + 1
tmpuser$ = Left$(args(1), xp - 1)
args(1) = Mid$(args(1), xp + 1)
newuser% = FindClient(tmpuser$)
If newuser% = -1 Then
SendError FromSock, 401, tmpuser$ + " :No such nick/channel"
Else
SM FromSock, ":" + ServerHost + " 311 " + Clients(FromSock).Nick + " " + Clients(newuser%).Nick + " " + Clients(newuser%).User + " " + Clients(newuser%).Host + " * :" + Clients(newuser%).RealName
If IsUserMode(newuser%, "ao") Then SM FromSock, ":" + ServerHost + " 313 " + Clients(FromSock).Nick + " " + Clients(newuser%).Nick + " :is an IRC operator"
SM FromSock, ":" + ServerHost + " 317 " + Clients(FromSock).Nick + " " + Clients(newuser%).Nick + Str$(UnixTimeEnc&(Date$, Timer) - Clients(newuser%).LastAction) + Str$(Clients(newuser%).ConnectTime) + " :seconds idle, signon time"
SM FromSock, ":" + ServerHost + " 318 " + Clients(FromSock).Nick + " " + Clients(newuser%).Nick + " :End of /WHOIS list"
End If
Loop Until Len(args(1)) = 0
Case "VERSION"
SM FromSock, ":" + ServerHost + " 351 " + Clients(FromSock).Nick + " 1.2 " + ServerHost + " :Running tsIRCd. Server is experimental and under development."
Case "KICK"
If Len(args(2)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
newchan = ChanExists(args(1))
If newchan > 0 Then
If IsUserChanMode(FromSock, newchan, "qo") = 0 Then SendError FromSock, 482, Chans(newchan).Title + " :You're not channel operator": Exit Sub
kickreason$ = Mid$(origline$, Len(args(1)) + Len(args(2)) + 2)
kickwho% = FindClient(args(2))
If kickwho% = -1 Then SendError FromSock, 401, args(1) + " :No such nick/channel": Exit Sub
If Clients(kickwho%).Chans(newchan) = 0 Then SendError FromSock, 441, Clients(kickwho%).Nick + " " + Chans(newchan).Title + " :They aren't on that channel": Exit Sub
BroadcastChan newchan, ":" + FullHost(FromSock) + " KICK " + Chans(newchan).Title + " " + Clients(kickwho%).Nick + " " + kickreason$, -1
Clients(kickwho%).Chans(newchan) = 0
Chans(newchan).UMode(kickwho%) = ""
Else
SendError FromSock, 403, args(1) + " :No such channel"
End If
Case "AWAY"
If Len(args(1)) = 0 Then
SM FromSock, ":" + ServerHost + " 305 " + Clients(FromSock).Nick + " :You are no longer marked as being away"
Clients(FromSock).IsAway = 0
Clients(FromSock).AwayMsg = ""
Else
SM FromSock, ":" + ServerHost + " 306 " + Clients(FromSock).Nick + " :You are now marked as being away"
Clients(FromSock).IsAway = 1
Clients(FromSock).AwayMsg = origline$
End If
Case "REHASH"
If IsUserMode(FromSock, "a") = 0 Then SendError FromSock, 481, Clients(FromSock).Nick + " :Permission Denied - You're not an IRC operator": Exit Sub
Select Case LCase$(args(1))
Case "motd"
RehashMOTD
For n = 0 To frmMain.Sock.UBound
If n > frmMain.Sock.UBound Then Exit For
If frmMain.Sock(n).State = sckConnected And IsUserMode(Int(n), "a") Then
SM Int(n), ":" + ServerHost + " NOTICE " + Clients(n).Nick + " :*** NOTICE: " + Chr$(2) + FullHost(FromSock) + Chr$(2) + " is forcing re-reading of MOTD file."
End If
Next n
Case Else
RehashConfig
For n = 0 To frmMain.Sock.UBound
If n > frmMain.Sock.UBound Then Exit For
If frmMain.Sock(n).State = sckConnected And IsUserMode(Int(n), "a") Then
SM Int(n), ":" + ServerHost + " NOTICE " + Clients(n).Nick + " :*** NOTICE: " + Chr$(2) + FullHost(FromSock) + Chr$(2) + " is rehashing server configuration file."
End If
Next n
End Select
Case "KILL"
If IsUserMode(FromSock, "ao") = 0 Then SendError FromSock, 481, Clients(FromSock).Nick + " :Permission Denied - You're not an IRC operator": Exit Sub
If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
killwho% = FindClient(args(1))
If killwho% = -1 Then SendError FromSock, 401, args(1) + " :No such nick/channel": Exit Sub
killreason$ = Mid$(origline$, Len(args(1)) + 2)
If Len(killreason$) = 0 Then killreason$ = "No reason given."
QuitClient killwho%, "Local kill by " + Clients(FromSock).Nick + " [Reason" + killreason$ + "]"
Case "ISON"
If Len(origline$) = 0 Then If Len(args(1)) = 0 Then SendError FromSock, 461, args(0) + " :Not enough parameters": Exit Sub
isonrpl$ = ""
Do
xp = InStr(1, origline$, " ")
If xp < 1 Then xp = Len(origline$) + 1
curnick$ = LTrim$(RTrim$(Left$(origline$, xp - 1)))
origline$ = Mid$(origline$, xp + 1)
If FindClient(curnick$) > -1 Then isonrpl$ = isonrpl$ + " " + curnick$
Loop Until Len(origline$) = 0
SM FromSock, ":" + ServerHost + " 303 " + Clients(FromSock).Nick + " :" + isonrpl$
Case "DIE"
If IsUserMode(FromSock, "a") = 0 Then SendError FromSock, 481, Clients(FromSock).Nick + " :Permission Denied - You're not an IRC administrator": Exit Sub
Shutdown "Command /DIE given by " + Clients(FromSock).Nick
Case "LIST"
SendList FromSock, args(1)
Case "PING"
SM FromSock, ":" + ServerHost + " PONG " + ServerHost + " " + origline$
Case "PONG"
Clients(FromSock).GotPong = 1
Case "QUIT"
QuitClient FromSock, origline$
Case Else
If Len(args(0)) > 0 Then SendError FromSock, 421, args(0) + " :Unknown command"
End Select
End Sub
Public Sub SendError(ToSock As Integer, ErrVal As Integer, Message As String)
SM ToSock, ":" + ServerHost + Str$(ErrVal) + " " + Clients(ToSock).Nick + " " + Message
End Sub
Public Function NormalizeNick$(InNick As String)
NewNick$ = ""
For n = 1 To Len(InNick)
cc$ = Mid$(InNick, n, 1)
If InStr(1, NickChars, LCase$(cc$)) < 1 Then cc$ = ""
NewNick$ = NewNick$ + cc$
Next n
NormalizeNick$ = Left$(NewNick$, NickLen)
End Function
Public Function NickInUse(CheckNick As String)
For n = 1 To SQct
If LCase$(CheckNick) = LCase$(Reserved(n)) Then NickInUse = True: Exit Function
Next n
For n = 0 To 1000
If LCase$(Clients(n).Nick) = LCase$(CheckNick) Then NickInUse = True: Exit Function
Next n
NickInUse = False
End Function
Public Function NormalizeChan$(InChan As String)
newchan$ = ""
For n = 1 To Len(InChan)
cc$ = Mid$(InChan, n, 1)
If InStr(1, ChanChars, LCase$(cc$)) < 1 Then cc$ = ""
newchan$ = newchan$ + cc$
Next n
NormalizeChan$ = Left$(newchan$, ChanLen)
End Function
Public Sub SendGreeting(ToSock As Integer)
SM ToSock, ":" + ServerHost + " 001 " + Clients(ToSock).Nick + " :Welcome to the " + Chr$(2) + ServerName + Chr$(2) + " Internet Relay Chat Network " + Clients(ToSock).Nick
SM ToSock, ":" + ServerHost + " 002 " + Clients(ToSock).Nick + " :Your host is " + ServerHost + "[" + frmMain.sckListen(0).LocalIP + "], running " + Build + ""
SM ToSock, ":" + ServerHost + " 003 " + Clients(ToSock).Nick + " :This server was created " + Creation
SM ToSock, ":" + ServerHost + " 004 " + Clients(ToSock).Nick + " " + ServerHost + " " + Build
SM ToSock, ":" + ServerHost + " 005 " + Clients(ToSock).Nick + " NICKLEN=" + Mid$(Str$(NickLen), 2) + " PREFIX=(qov)~@+ STATUSMSG=~@+ TOPICLEN=" + Mid$(Str$(TopicLen), 2) + " NETWORK=" + ServerName + " MAXTARGETS=1 CHANTYPES=# :are supported by this server"
SM ToSock, ":" + ServerHost + " 005 " + Clients(ToSock).Nick + " CHANLIMIT=#:50 CHANMODES=bklmt AWAYLEN=160 :are supported by this server"
SM ToSock, ":" + ServerHost + " 251 " + Clients(ToSock).Nick + " :There are" + Str$(OnlineCount) + " clients and 1 servers"
SM ToSock, ":" + ServerHost + " 254 " + Clients(ToSock).Nick + Str$(ChanCount) + " :channels formed"
SM ToSock, ":" + ServerHost + " 265 " + Clients(ToSock).Nick + " :Current local users:" + Str$(OnlineCount) + " Max: 1000"
SendMOTD ToSock
If ServType = 1 Then NickCheck ToSock, Clients(ToSock).Nick
End Sub
Public Function OnlineCount()
tmpcount = 0
For n = 0 To frmMain.Sock.UBound
If frmMain.Sock(n).State = sckConnected Then tmpcount = tmpcount + 1
Next n
OnlineCount = tmpcount
End Function
Public Function ChanCount()
tmpcount = 0
For n = 0 To 1000
If Len(Chans(n).Title) > 0 Then tmpcount = tmpcount + 1
Next n
ChanCount = tmpcount
End Function
Public Sub RehashMOTD()
nf = FreeFile
Open WorkDir + "MOTD.TXT" For Binary As #nf: Close #nf
Open WorkDir + "MOTD.TXT" For Input As #nf
MOTD = ""
Do Until EOF(nf)
Line Input #nf, tmpin$
If Len(tmpin$) = 0 Then tmpin$ = " "
MOTD = MOTD + tmpin$ + vbCrLf
Loop
Close #nf
End Sub
Public Sub SendMOTD(ToSock As Integer)
SM ToSock, ":" + ServerHost + " 375 " + Clients(ToSock).Nick + " :" + ServerHost + " Message Of The Day"
tmpmotd$ = MOTD
Do Until Len(tmpmotd$) = 0
xp = InStr(1, tmpmotd$, vbCrLf)
SM ToSock, ":" + ServerHost + " 372 " + Clients(ToSock).Nick + " :" + Left$(tmpmotd$, xp - 1)
tmpmotd$ = Mid$(tmpmotd$, xp + 2)
Loop
SM ToSock, ":" + ServerHost + " 376 " + Clients(ToSock).Nick + " :End of /MOTD"
End Sub
Public Function FullHost$(SockVal As Integer)
FullHost$ = Clients(SockVal).Nick + "!" + Clients(SockVal).User + "@" + Clients(SockVal).Host
End Function
Public Function UnixTimeEnc&(dateval As String, ByVal timeval As Long)
'On Error Resume Next
Dim temptime, month, day, year As Long
timezone% = -6
tempdate$ = dateval
divider = InStr(1, tempdate$, "-"): month = Val(Left$(tempdate$, divider - 1))
tempdate$ = Mid$(tempdate$, divider + 1)
divider = InStr(1, tempdate$, "-"): day = Val(Left$(tempdate$, divider - 1))
tempdate$ = Mid$(tempdate$, divider + 1)
year = Val(tempdate$)
temptime = 0
For calcval = 1970 To year - 1
'determine if a year is a leap year
If (calcval + 2) / 4 = Fix((calcval + 2) / 4) Then
daysinyear = 366
Else
daysinyear = 365
End If
temptime = temptime + (daysinyear * 86400)
Next calcval
For calcval = 1 To month - 1
Select Case calcval
Case 1, 3, 5, 7, 8, 10, 11, 12 '31 day months
temptime = temptime + (31 * 86400)
Case 2 'Feb = 28 days in common year, 29 days in leap year
If (year + 2) / 4 = Fix((year + 2) / 4) Then 'it's a leap year
temptime = temptime + (29 * 86400)
Else 'it's a common year
temptime = temptime + (28 * 86400)
End If
Case Else
temptime = temptime + (30 * 86400)
End Select
Next calcval
temptime = temptime + ((day - 1) * 86400) + timeval + (-timezone * 3600)
UnixTimeEnc& = temptime - (3600 * timezone%)
End Function
Public Sub DoPing(SockVal As Integer)
Clients(SockVal).GotPong = 0
pingtime& = UnixTimeEnc&(Date$, Timer)
Clients(SockVal).LastPing = pingtime&
SM SockVal, "PING :" + ServerHost
End Sub
Public Sub QuitClient(SockVal As Integer, Reason As String)
SM SockVal, "ERROR :Closing Link: " + Clients(SockVal).Nick + "[" + Clients(SockVal).Host + " (" + Reason + ")"
KillFlag(SockVal) = 1
frmMain.Sock(SockVal).Close
For n = 1 To 1000
If Clients(SockVal).Chans(n) = 1 Then
Clients(SockVal).Chans(n) = 0
userchancount% = 0
For nu = 0 To frmMain.Sock.UBound
If nu > frmMain.Sock.UBound Then Exit For
If Clients(nu).Chans(n) = 1 Then userchancount% = userchancount% + 1
Next nu
If userchancount% > 0 Then
If InStr(1, Reason, ":") < 1 Then extra$ = ":" Else extra$ = ""
BroadcastChan Int(n), ":" + FullHost(SockVal) + " QUIT " + extra$ + Reason, SockVal
Else
ClearChanSlot Int(n)
End If
End If
Next n
End Sub
Public Function JoinChan(SockVal As Integer, ChannelName As String, ChannelKey As String) As Integer
Dim newchan As Integer
newchan = ChanExists(ChannelName)
If newchan = 0 Then newchan = CreateChan(ChannelName): Chans(newchan).Key = ChannelKey: makeop = 1 Else makeop = 0
If Clients(SockVal).Chans(newchan) = 0 Then
For n = 0 To 1000 'see if banned
If Len(Chans(newchan).Bans(n)) > 0 And MatchMask%(FullHost(SockVal), Chans(newchan).Bans(n)) = 1 Then SendError SockVal, 474, Chans(newchan).Title + " :Cannot join channel (+b)": Exit Function
Next n
If IsChanMode(newchan, "k") Then
If Chans(newchan).Key <> ChannelKey Then SendError SockVal, 475, Chans(newchan).Title + " :Cannot join channel (+k)": Exit Function
End If
If IsChanMode(newchan, "i") Then
If Clients(SockVal).Invite(newchan) = 0 Then SendError SockVal, 473, Chans(newchan).Title + " :Cannot join channel (+i)": Exit Function
End If
If IsChanMode(newchan, "l") Then
If Chans(newchan).ULimit > 0 Then
usersinchan% = 0
For nu = 0 To frmMain.Sock.UBound
If nu > frmMain.Sock.UBound Then Exit For
If Clients(nu).Chans(newchan) = 1 Then usersinchan% = usersinchan% + 1
Next nu
If usersinchan% >= Chans(newchan).ULimit Then SendError SockVal, 471, Chans(newchan).Title + " :Cannot join channel (+l)": Exit Function
End If
End If
Clients(SockVal).Chans(newchan) = 1
JoinChan = newchan
SM SockVal, ":" + ServerHost + " 366 " + Clients(SockVal).Nick + " " + Chans(newchan).Title + " :End of /NAMES list"
If makeop = 1 Then
Chans(newchan).Created = UnixTimeEnc&(Date$, Timer)
Chans(newchan).IndexDB = 0
For n = 1 To ChanDBCount
If LCase$(ChannelName) = LCase$(Chans(n).Title) Then Chans(newchan).IndexDB = n: Exit For
Next n
If Chans(newchan).IndexDB > 0 Then
Chans(newchan).Topic = ChanDB(Chans(newchan).IndexDB).Topic
Chans(newchan).TopicUser = ChanDB(Chans(newchan).IndexDB).TopicUser
Chans(newchan).TopicTime = ChanDB(Chans(newchan).IndexDB).TopicTime
End If
SetChanMode newchan, ServerHost, "n"
SetUserChanMode newchan, ServerHost, SockVal, "o"
End If
BroadcastChan newchan, ":" + FullHost(SockVal) + " JOIN " + Chans(newchan).Title, -1
'SendModes SockVal, newchan
SendNames SockVal, newchan
If Len(Chans(newchan).Topic) > 0 Then SendTopic SockVal, newchan
End If
'If Chans(newchan).IndexDB > 0 Then
ChanMaint newchan
End Function
Public Function CreateChan(ChannelName As String)
For n = 1 To 1000
If Len(Chans(n).Title) = 0 Then Chans(n).Title = ChannelName: CreateChan = n: Exit Function
Next n
End Function
Public Function ChanExists(ChannelName As String)
For n = 1 To 1000
If LCase$(Chans(n).Title) = LCase$(ChannelName) Then ChanExists = n: Exit Function
Next n
End Function
Public Sub SendTopic(SockVal As Integer, ChanVal As Integer)
If Len(Chans(ChanVal).Topic) = 0 Then
SM SockVal, ":" + ServerHost + " 331 " + Clients(SockVal).Nick + " " + Chans(ChanVal).Title + " :No topic is set"
Else
SM SockVal, ":" + ServerHost + " 332 " + Clients(SockVal).Nick + " " + Chans(ChanVal).Title + Chans(ChanVal).Topic
SM SockVal, ":" + ServerHost + " 333 " + Clients(SockVal).Nick + " " + Chans(ChanVal).Title + " " + Chans(ChanVal).TopicUser + Str$(Chans(ChanVal).TopicTime)
End If
End Sub
Public Sub BroadcastChan(ChanVal As Integer, Message As String, Exclude As Integer)
Dim n As Integer
If ChanVal = 0 Then Exit Sub
For n = 0 To 1000
If Clients(n).Chans(ChanVal) = 1 And n <> Exclude Then SM n, Message: DoEvents
Next n
End Sub
Public Sub PartChan(SockVal As Integer, ChanVal As Integer, Reason As String)
BroadcastChan ChanVal, ":" + FullHost(SockVal) + " PART " + Chans(ChanVal).Title + " :" + Reason, -1
Clients(SockVal).Chans(ChanVal) = 0
Chans(ChanVal).UMode(SockVal) = ""
For n = 0 To frmMain.Sock.UBound
For nu = 1 To 1000
If Clients(n).Chans(nu) = 1 Then Exit Sub
Next nu
Next n
'since nobody is left, we reset all channel number info here
ClearChanSlot ChanVal
End Sub
Public Sub SendNames(ToSock As Integer, ChanVal As Integer)
ct = 0
tmpnames$ = ":" + ServerHost + " 353 " + Clients(ToSock).Nick + " = " + Chans(ChanVal).Title + " :"
For n = 0 To frmMain.Sock.UBound
If Clients(n).Chans(ChanVal) = 1 Then
tmpnick$ = Clients(n).Nick
If InStr(1, Chans(ChanVal).UMode(n), "v") Then tmpnick$ = "+" + Clients(n).Nick
If InStr(1, Chans(ChanVal).UMode(n), "o") Then tmpnick$ = "@" + Clients(n).Nick
If InStr(1, Chans(ChanVal).UMode(n), "q") Then tmpnick$ = "~" + Clients(n).Nick
tmpnames$ = tmpnames$ + tmpnick$
ct = ct + 1
If ct = 12 Then
SM ToSock, tmpnames$
tmpnames$ = ":" + ServerHost + " 353 " + Clients(ToSock).Nick + " = " + Chans(ChanVal).Title + " :"
ct = 0
Else
tmpnames$ = tmpnames$ + " "
End If
End If
Next n
If ct < 12 Then SM ToSock, tmpnames$
End Sub
Public Function IsChanMode(ChanVal As Integer, Modes As String)
For n = 1 To Len(Modes)
If InStr(1, Chans(ChanVal).Modes, Mid$(Modes, n, 1)) Then IsChanMode = 1: Exit Function
Next n
End Function
Public Function IsUserChanMode(SockVal As Integer, ChanVal As Integer, Modes As String)
For n = 1 To Len(Modes)
If InStr(1, Chans(ChanVal).UMode(SockVal), Mid$(Modes, n, 1)) > 0 Then IsUserChanMode = 1: Exit Function
Next n
End Function
Public Function IsUserMode(SockVal As Integer, WhatMode As String)
For n = 1 To Len(WhatMode)
cc$ = Mid$(WhatMode, n, 1)
If InStr(1, Clients(SockVal).Modes, cc$) Then IsUserMode = 1: Exit Function
Next n
End Function
Public Sub ChangeNick(SockVal As Integer, NewNick As String)
tmpub = frmMain.Sock.UBound
For n = 0 To tmpub
Temp(n) = 0
Next n
For n = 0 To tmpub
For nu = 1 To 1000
If Clients(n).Chans(nu) = Clients(SockVal).Chans(nu) Then Temp(n) = 1
Next nu
Next n
Temp(SockVal) = 1
For n = 0 To tmpub
If Temp(n) = 1 Then SM Int(n), ":" + FullHost(SockVal) + " NICK " + NewNick
Next n
Clients(SockVal).NickTimer = 0
Clients(SockVal).Nick = NewNick
End Sub
Public Sub SetChanMode(ChanVal As Integer, ByWho As String, WhatMode As String)
BroadcastChan ChanVal, ":" + ByWho + " MODE " + Chans(ChanVal).Title + " :+" + WhatMode + extra$, -1
For n = 1 To Len(WhatMode)
cc$ = Mid$(WhatMode, n, 1)
If InStr(1, Chans(ChanVal).Modes, cc$) < 1 Then Chans(ChanVal).Modes = Chans(ChanVal).Modes + cc$
Select Case cc$
Case "s"
UnSetChanMode ChanVal, ServerHost, "p"
Case "p"
UnSetChanMode ChanVal, ServerHost, "s"
End Select
Next n
'If ByWho <> "ChanServ" Then ChanMaint ChanVal
End Sub
Public Sub SetUserMode(UserVal As Integer, ByWho As String, WhatMode As String)
SM UserVal, ":" + ByWho + " MODE " + Clients(UserVal).Nick + " +" + WhatMode
For n = 1 To Len(WhatMode)
cc$ = Mid$(WhatMode, n, 1)
If InStr(1, Clients(UserVal).Modes, cc$) < 1 Then Clients(UserVal).Modes = Clients(UserVal).Modes + cc$
Next n
End Sub
Public Sub SetUserChanMode(ChanVal As Integer, ByWho As String, UserVal As Integer, WhatMode As String)
If UserVal < 0 Then Exit Sub
For n = 1 To Len(WhatMode)
cc$ = Mid$(WhatMode, n, 1)
If InStr(1, Chans(ChanVal).UMode(UserVal), cc$) < 1 Then
BroadcastChan ChanVal, ":" + ByWho + " MODE " + Chans(ChanVal).Title + " +" + cc$ + " " + Clients(UserVal).Nick, -1
Chans(ChanVal).UMode(UserVal) = Chans(ChanVal).UMode(UserVal) + cc$
End If
Next n
'If ByWho <> "ChanServ" Then ChanMaint ChanVal
End Sub
Public Sub UnSetUserChanMode(ChanVal As Integer, ByWho As String, UserVal As Integer, WhatMode As String)
If UserVal < 0 Then Exit Sub
For n = 1 To Len(WhatMode)
cc$ = Mid$(WhatMode, n, 1)
xp = InStr(1, Chans(ChanVal).UMode(UserVal), cc$)
If xp > 0 Then
'If xp = 1 Then
' Chans(ChanVal).UMode(UserVal) = Mid$(Chans(ChanVal).UMode(UserVal), 2)
'Else
BroadcastChan ChanVal, ":" + ByWho + " MODE " + Chans(ChanVal).Title + " -" + cc$ + " " + Clients(UserVal).Nick, -1
Chans(ChanVal).UMode(UserVal) = Left$(Chans(ChanVal).UMode(UserVal), xp - 1) + Mid$(Chans(ChanVal).UMode(UserVal), xp + 1)
'End If
End If
Next n
'If ByWho <> "ChanServ" Then ChanMaint ChanVal
End Sub
Public Sub UnSetChanMode(ChanVal As Integer, ByWho As String, WhatMode As String)
For n = 1 To Len(WhatMode)
cc$ = Mid$(WhatMode, n, 1)
xp = InStr(1, Chans(ChanVal).Modes, cc$)
If xp > 0 Then
'If xp = 1 Then
' Chans(ChanVal).Modes = Mid$(Chans(ChanVal).Modes, 2)
'Else
BroadcastChan ChanVal, ":" + ByWho + " MODE " + Chans(ChanVal).Title + " -" + WhatMode, -1
Chans(ChanVal).Modes = Left$(Chans(ChanVal).Modes, xp - 1) + Mid$(Chans(ChanVal).Modes, xp + 1)
'End If
End If
Next n
'If ByWho <> "ChanServ" Then ChanMaint ChanVal
End Sub
Public Sub UnSetUserMode(UserVal As Integer, ByWho As String, WhatMode As String)
For n = 1 To Len(WhatMode)
cc$ = Mid$(WhatMode, n, 1)
xp = InStr(1, Clients(UserVal).Modes, cc$)
If xp > 0 Then
'If xp = 1 Then
' Clients(UserVal).Modes = Mid$(Clients(UserVal).Modes, 2)
'Else
SM UserVal, ":" + ByWho + " MODE " + Clients(UserVal).Nick + " -" + WhatMode
Clients(UserVal).Modes = Left$(Clients(UserVal).Modes, xp - 1) + Mid$(Clients(UserVal).Modes, xp + 1)
'End If
End If
Next n
End Sub
Public Function FindClient(NickName As String)
For n = 0 To frmMain.Sock.UBound
If LCase$(Clients(n).Nick) = LCase$(NickName) Then FindClient = n: Exit Function
Next n
FindClient = -1
End Function
Public Sub SendList(SockVal As Integer, Contains As String)
SM SockVal, ":" + ServerHost + " 321 " + Clients(SockVal).Nick + " Channel :Users Name"
For n = 1 To 1000
If Len(Contains) = 0 Then
If Len(Chans(n).Title) > 0 Then showit = 1 Else showit = 0
Else
If InStr(1, LCase$(Chans(n).Title), LCase$(Contains)) Then showit = 1 Else showit = 0
End If
If IsChanMode(Int(n), "sp") Then showit = 0
If showit = 1 Then
usersinchan% = 0
For nu = 0 To frmMain.Sock.UBound
If Clients(nu).Chans(n) = 1 Then usersinchan% = usersinchan% + 1
Next nu
SM SockVal, ":" + ServerHost + " 322 " + Clients(SockVal).Nick + " " + Chans(n).Title + Str$(usersinchan%) + Chans(n).Topic
End If
Next n
SM SockVal, ":" + ServerHost + " 323 " + Clients(SockVal).Nick + " :End of /LIST"
End Sub
Public Function MatchMask%(check$, against$)
chk$ = against$
tmp$ = check$
Match% = 1
For chkm = 1 To Len(chk$)
curchar$ = Mid$(chk$, chkm, 1)
nextchar$ = Mid$(chk$, chkm + 1, 1)
If curchar$ = "*" Then
If Len(nextchar$) = 0 Then Exit For
xpm = InStr(tmp$, nextchar$)
If xpm < 1 Then Match% = 0: Exit For
tmp$ = Mid$(tmp$, xpm + 1)
chkm = chkm + 1
Else
If Left$(tmp$, 1) <> curchar$ Then Match% = 0: Exit For
tmp$ = Mid$(tmp$, 2)
End If
If Len(tmp$) = 0 Then Exit For
Next chkm
MatchMask% = Match%
End Function
Public Sub ClearChanSlot(ChanVal As Integer)
Chans(ChanVal).Modes = ""
Chans(ChanVal).Title = ""
Chans(ChanVal).Topic = ""
Chans(ChanVal).TopicTime = 0
Chans(ChanVal).TopicUser = ""
Chans(ChanVal).Created = 0
Chans(ChanVal).Key = ""
Chans(ChanVal).ULimit = 0
Chans(ChanVal).IndexDB = 0
For n = 0 To 1000
Chans(ChanVal).UMode(n) = ""
Chans(ChanVal).Bans(n) = ""
Next n
End Sub
Public Function IsRsvd(CheckNick As String)
'For n = 1 To SQct
' If LCase$(CheckNick) = LCase$(Reserved(n)) Then IsRsvd = 1: Exit Function
'Next n
Select Case LCase$(CheckNick)
Case "nickserv", "chanserv", "operserv", "memoserv", "hostserv"
IsRsvd = 1
Case Else
IsRsvd = 0
End Select
End Function
Public Sub Shutdown(Reason As String)
For n = 0 To frmMain.sckListen.UBound
frmMain.sckListen(n).Close
Next n
For n = 0 To frmMain.Sock.UBound
If n > frmMain.Sock.UBound Then Exit For
If frmMain.Sock(n).State = sckConnected Then
SM Int(n), ":" + ServerHost + " NOTICE " + Clients(n).Nick + " :" + Reason
QuitClient Int(n), "Server shutdown."
End If
Next n
frmMain.DieTimer.Enabled = True
End Sub
Public Sub SendModes(ToSock As Integer, ChanVal As Integer)
For n = 1 To Len(Chans(ChanVal).Modes)
Select Case Mid$(Chans(ChanVal).Modes, n, 1)
Case "l"
extra$ = extra$ + Str$(Chans(ChanVal).ULimit)
End Select
Next n
SM ToSock, ":" + ServerHost + " 324 " + Clients(ToSock).Nick + " " + Chans(ChanVal).Title + " +" + Chans(ChanVal).Modes + extra$
End Sub