Skip to content

Commit 2d52462

Browse files
author
Mitch Rodrigues
committed
Add OPER also add KILL and SNOTICE's into various spots (Still todo configure oper perms etc)
1 parent 09a5c98 commit 2d52462

6 files changed

Lines changed: 168 additions & 33 deletions

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.1e
1+
0.0.1f

ircd/channel.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func (c *Channel) SetTopic(cli *Client, topic string) {
6868
func (c *Channel) sendTopicNumeric(cli *Client) {
6969
if c.Topic != "" {
7070
cli.SendNumeric(RPL_TOPIC, c.Name, c.Topic+" ")
71-
cli.SendNumeric(RPL_TOPICTIME, c.Name, fmt.Sprintf("%d", c.TopicTime.Unix()))
71+
cli.SendNumeric(RPL_TOPICTIME, c.Name, c.TopicSetter, fmt.Sprintf("%d", c.TopicTime.Unix()))
7272
}
7373
}
7474

@@ -115,15 +115,26 @@ func (c *Channel) ClientCan(cli *Client, permName string) bool {
115115
return false
116116
}
117117

118-
func (c *Channel) ModePrefixFor(cli *Client) string {
118+
func (c *Channel) AllModePrefixesFor(cli *Client) string {
119+
var str string
120+
119121
if c.IsOperator(cli) {
120-
return "@"
122+
str += "@"
121123
}
122124
if c.IsHalfOp(cli) {
123-
return "%"
125+
str += "%"
124126
}
127+
125128
if c.IsVoice(cli) {
126-
return "+"
129+
str += "+"
130+
}
131+
132+
return str
133+
}
134+
135+
func (c *Channel) ModePrefixFor(cli *Client) string {
136+
if str := c.AllModePrefixesFor(cli); str != "" {
137+
return string(str[0])
127138
}
128139
return ""
129140
}

ircd/client.go

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"time"
1010

11+
"nxircd/config"
1112
"nxircd/interfaces"
1213
"strings"
1314
)
@@ -51,6 +52,9 @@ type Client struct {
5152

5253
local bool
5354

55+
Operator bool
56+
operconf config.IRCOp
57+
5458
capState int
5559
capVersion int
5660

@@ -84,7 +88,7 @@ func (c *Client) Run() {
8488

8589
clientPreflight(c)
8690

87-
for err == nil {
91+
for err == nil && c.connected {
8892
line, err := c.sock.Read()
8993
if err != nil {
9094
if c.connected {
@@ -126,8 +130,21 @@ func (c *Client) Prefix() string {
126130
return ""
127131
}
128132

133+
func (c *Client) Oper(oconf config.IRCOp) {
134+
c.ApplyModes(c.HostMask(), 'o', 's')
135+
136+
c.SendNumeric(RPL_YOUREOPER, c.Nick, "You are now an IRC Operator")
137+
138+
c.Operator = true
139+
c.operconf = oconf
140+
141+
c.Server.SNotice(fmt.Sprintf("%s (%s) [%s] is now an operator.", c.Nick, c.IdentHost(), c.operconf.User))
142+
143+
c.Server.IRCOps[c] = true
144+
}
145+
129146
// This is ugly but im tired so lets leave it be for now
130-
func (c *Client) ApplyModeChanges(changes []ModeChange) {
147+
func (c *Client) ApplyModeChanges(prefix string, changes []ModeChange) {
131148

132149
addString := ""
133150
delString := ""
@@ -147,13 +164,17 @@ func (c *Client) ApplyModeChanges(changes []ModeChange) {
147164
}
148165

149166
if addString != "" {
150-
c.Send(c.Nick, "MODE", c.Nick, "+"+addString)
167+
c.Send(prefix, "MODE", c.Nick, "+"+addString)
151168
}
152169
if delString != "" {
153-
c.Send(c.Nick, "MODE", c.Nick, "-"+delString)
170+
c.Send(prefix, "MODE", c.Nick, "-"+delString)
154171
}
155172
}
156173

174+
func (c *Client) IdentHost() string {
175+
return fmt.Sprintf("%s@%s", c.Ident, c.Host)
176+
}
177+
157178
func (c *Client) RealHostMask() string {
158179
return fmt.Sprintf("%s!%s@%s", c.Nick, c.Ident, c.RealHost)
159180
}
@@ -186,10 +207,15 @@ func (c *Client) IPMask() string {
186207
return fmt.Sprintf("%s!%s@%s", c.Nick, c.Ident, c.IP)
187208
}
188209

189-
func (c *Client) ApplyModes(ms ...Mode) {
210+
func (c *Client) ApplyModes(source string, ms ...Mode) {
211+
modes := ""
190212
for _, m := range ms {
191213
c.Modes.Add(m, "")
214+
modes += m.String()
192215
}
216+
217+
c.Send(source, "MODE", c.Nick, "+"+modes)
218+
193219
}
194220

195221
func (c *Client) Quit(msg string) {
@@ -198,6 +224,10 @@ func (c *Client) Quit(msg string) {
198224
channel.Quit(c, msg)
199225
c.Channels.Delete(channel)
200226
}
227+
228+
c.connected = false
229+
230+
c.Server.SNotice(fmt.Sprintf("Client exiting: %s (%s@%s) [%s] (Quit: %s)", c.Nick, c.Ident, c.RealHost, c.IP, msg))
201231
c.Server.RemoveClient(c)
202232
}
203233

ircd/commands.go

Lines changed: 100 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"strings"
66
"time"
7+
8+
"nxircd/config"
79
)
810

911
type ClientCmd struct {
@@ -86,10 +88,39 @@ var clientCmdMap = map[string]ClientCmd{
8688
minParams: 1,
8789
handler: whoisUCmdHandler,
8890
},
91+
"NAMES": {
92+
minParams: 1,
93+
handler: namesUCmdHandler,
94+
},
95+
"OPER": {
96+
minParams: 2,
97+
handler: operUCmdHandler,
98+
},
99+
"KILL": {
100+
minParams: 1,
101+
handler: killUCmdHandler,
102+
},
103+
}
104+
105+
func namesUCmdHandler(srv *Server, cli *Client, m *Message) error {
106+
target := m.Args[0]
107+
108+
if ValidChannel(target) {
109+
ch := srv.FindChannel(target)
110+
if ch == nil {
111+
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "no such channel")
112+
return fmt.Errorf("no such channel")
113+
}
114+
ch.Names(cli)
115+
return nil
116+
}
117+
118+
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "invalid channel name")
119+
return fmt.Errorf("invalid channel")
89120
}
90121

91122
func pingUCmdHandler(src *Server, cli *Client, m *Message) error {
92-
cli.SendFromServer("PING", fmt.Sprintf("%d", time.Now().Unix()))
123+
cli.SendFromServer("PONG", fmt.Sprintf("%d", time.Now().Unix()))
93124
return nil
94125
}
95126

@@ -98,13 +129,13 @@ func nickUCmdHandler(srv *Server, cli *Client, m *Message) error {
98129

99130
if srv.NickInUse(nick) {
100131
// TODO Send no such nick
101-
cli.SendNumeric(ERR_NICKNAMEINUSE, nick, "*", "nick in use")
132+
cli.SendNumeric(ERR_NICKNAMEINUSE, nick, "nick in use")
102133
return fmt.Errorf("nick in use")
103134
}
104135

105136
if !ValidNick(nick) {
106137
// This is what unreal sends? cray
107-
cli.SendNumeric(ERR_NICKNAMEINUSE, nick, "*", "Nickname is unavailable: Illegal characters")
138+
cli.SendNumeric(ERR_NICKNAMEINUSE, nick, "Nickname is unavailable: Illegal characters")
108139
return fmt.Errorf("invalid nick")
109140
}
110141

@@ -124,9 +155,12 @@ func userUCmdHandler(srv *Server, cli *Client, m *Message) error {
124155

125156
cli.Ident = m.Args[0]
126157
cli.Name = m.Args[3]
158+
cli.registered = true
127159

128160
srv.Greet(cli)
129161

162+
srv.SNotice(fmt.Sprintf("Client connecting: %s (%s@%s) [%s] on %s", cli.Nick, cli.Ident, cli.RealHost, cli.IP, cli.Server.Name))
163+
130164
srv.Log.InfoF("Client Connected: %s", cli.HostMask())
131165

132166
return nil
@@ -187,13 +221,8 @@ func whoUCmdHandler(srv *Server, cli *Client, m *Message) error {
187221
}
188222

189223
func quitUCmdHandler(srv *Server, cli *Client, m *Message) error {
190-
msg := m.Args[0]
191-
192-
for _, ch := range cli.Channels.list {
193-
ch.Quit(cli, msg)
194-
}
195-
196224
srv.Clients.Delete(cli)
225+
cli.Quit(m.Args[0])
197226
return nil
198227
}
199228

@@ -229,7 +258,7 @@ func msgUCmdHandler(srv *Server, cli *Client, m *Message) error {
229258
if ValidChannel(target) {
230259
ch := srv.FindChannel(target)
231260
if ch == nil {
232-
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "*", "no such channel")
261+
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "no such channel")
233262
return fmt.Errorf("no such channel")
234263
}
235264
ch.PrivMsg(cli, m.Args[1])
@@ -238,7 +267,7 @@ func msgUCmdHandler(srv *Server, cli *Client, m *Message) error {
238267

239268
ct := srv.FindClient(target)
240269
if ct == nil {
241-
cli.SendNumeric(ERR_NOSUCHNICK, target, "*", "no such nick")
270+
cli.SendNumeric(ERR_NOSUCHNICK, target, "no such nick")
242271
return fmt.Errorf("no such nick")
243272
}
244273

@@ -252,7 +281,7 @@ func noticeUCmdHandler(srv *Server, cli *Client, m *Message) error {
252281
if ValidChannel(target) {
253282
ch := srv.FindChannel(target)
254283
if ch == nil {
255-
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "*", "no such channel")
284+
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "no such channel")
256285
return fmt.Errorf("no such channel")
257286
}
258287
ch.Notice(cli, m.Args[1])
@@ -289,12 +318,12 @@ func modeUCmdHandler(srv *Server, cli *Client, m *Message) error {
289318
if ValidNick(target) {
290319
client := srv.FindClient(target)
291320
if client == nil {
292-
cli.SendNumeric(ERR_NOSUCHNICK, target, "*", "no such nickname")
321+
cli.SendNumeric(ERR_NOSUCHNICK, target, "no such nickname")
293322
return nil
294323
}
295324

296325
changes := ParseUMode(m.Args[1:]...)
297-
client.ApplyModeChanges(changes)
326+
client.ApplyModeChanges(cli.Nick, changes)
298327
}
299328

300329
return nil
@@ -304,13 +333,13 @@ func topicUCmdHandler(srv *Server, cli *Client, m *Message) error {
304333
target := m.Args[0]
305334

306335
if !ValidChannel(target) {
307-
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "*", "no such channel: invalid channel name")
336+
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "no such channel: invalid channel name")
308337
return fmt.Errorf("invalid channel")
309338
}
310339

311340
ch := srv.FindChannel(target)
312341
if ch == nil {
313-
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "*", "no such channel")
342+
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "no such channel")
314343
return fmt.Errorf("no such channel")
315344
}
316345

@@ -320,7 +349,7 @@ func topicUCmdHandler(srv *Server, cli *Client, m *Message) error {
320349
}
321350

322351
if !ch.IsOperator(cli) {
323-
cli.SendNumeric(ERR_NOPRIVS, target, "topic", "invalid permissions")
352+
cli.SendNumeric(ERR_NOPRIVILEGES, target, target, "topic: no permission.")
324353
return fmt.Errorf("no privs")
325354
}
326355
ch.SetTopic(cli, m.Args[1])
@@ -330,18 +359,18 @@ func topicUCmdHandler(srv *Server, cli *Client, m *Message) error {
330359
func kickUCmdHandler(srv *Server, cli *Client, m *Message) error {
331360
target := m.Args[0]
332361
if !ValidChannel(target) {
333-
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "*", "no such channel: invalid channel name")
362+
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "no such channel: invalid channel name")
334363
return fmt.Errorf("invalid channel")
335364
}
336365

337366
ch := srv.FindChannel(target)
338367
if ch == nil {
339-
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "*", "no such channel")
368+
cli.SendNumeric(ERR_NOSUCHCHANNEL, target, "no such channel")
340369
return fmt.Errorf("no such channel")
341370
}
342371

343372
if !ch.IsHalfOp(cli) && !ch.IsOperator(cli) {
344-
cli.SendNumeric(ERR_NOPRIVILEGES, "kick", target, "no permissions.")
373+
cli.SendNumeric(ERR_NOPRIVILEGES, target, "kick: no permissions.")
345374
return fmt.Errorf("no permissions")
346375
}
347376

@@ -367,7 +396,7 @@ func listUCmdHandler(srv *Server, cli *Client, m *Message) error {
367396
for _, channel := range srv.Channels.list {
368397
cli.SendNumeric(RPL_LIST, channel.Name, fmt.Sprintf("%d", channel.Clients.Count()), fmt.Sprintf("[+%s] %s", channel.Modes.FlagString(), channel.Topic))
369398
}
370-
cli.SendNumeric(RPL_LISTEND, "*", "end of /LIST")
399+
cli.SendNumeric(RPL_LISTEND, "End of /LIST")
371400

372401
return nil
373402
}
@@ -382,3 +411,53 @@ func whoisUCmdHandler(srv *Server, cli *Client, m *Message) error {
382411
cli.Whois(target)
383412
return nil
384413
}
414+
415+
func operUCmdHandler(srv *Server, cli *Client, m *Message) error {
416+
var oc *config.IRCOp
417+
418+
for _, oconf := range srv.Config.IrcOps {
419+
if oconf.User == m.Args[0] {
420+
oc = &oconf
421+
break
422+
}
423+
}
424+
425+
if oc == nil {
426+
srv.SNotice(fmt.Sprintf("Failed oper attempt by %s (%s) [unknown acct]", cli.Nick, cli.IdentHost()))
427+
return fmt.Errorf("invalid oper attempt (user)")
428+
}
429+
430+
if oc.Pass != m.Args[1] {
431+
srv.SNotice(fmt.Sprintf("Failed oper attempt by %s (%s) [%s] invalid password", cli.Nick, cli.IdentHost(), oc.User))
432+
return fmt.Errorf("invalid oper attempt (pass)")
433+
}
434+
435+
cli.Oper(*oc)
436+
return nil
437+
}
438+
439+
func killUCmdHandler(srv *Server, cli *Client, m *Message) error {
440+
target := m.Args[0]
441+
442+
ct := srv.FindClient(target)
443+
if ct == nil {
444+
cli.SendNumeric(ERR_NOSUCHNICK, target, "no such nick")
445+
return fmt.Errorf("no such nick")
446+
}
447+
448+
msg := "no reason"
449+
if len(m.Args) > 1 {
450+
msg = m.Args[1]
451+
}
452+
453+
quitmsg := fmt.Sprintf("Killed by %s (%s)", cli.Nick, msg)
454+
455+
ct.Send("", "ERROR", fmt.Sprintf("Closing link: %s [%s] %s (%s)", ct.Nick, ct.RealHost, cli.Nick, quitmsg))
456+
457+
ct.sock.Close()
458+
459+
// Received KILL message for [email protected] from _Twitch Path: manager.centralchat.net!_Twitch (.)
460+
srv.SNotice(fmt.Sprintf("Received KILL message for %s from %s Path: %s!%s (%s)", ct.HostMask(), cli.Nick, cli.Host, cli.Ident, quitmsg))
461+
462+
return nil
463+
}

0 commit comments

Comments
 (0)