Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

capability.go 3.1KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright (c) 2012-2014 Jeremy Latt
  2. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  3. // released under the MIT license
  4. package irc
  5. import (
  6. "strings"
  7. "github.com/goshuirc/irc-go/ircmsg"
  8. "github.com/oragono/oragono/irc/caps"
  9. )
  10. var (
  11. // SupportedCapabilities are the caps we advertise.
  12. // MaxLine, SASL and STS are set during server startup.
  13. SupportedCapabilities = caps.NewSet(caps.AccountTag, caps.AccountNotify, caps.AwayNotify, caps.CapNotify, caps.ChgHost, caps.EchoMessage, caps.ExtendedJoin, caps.InviteNotify, caps.Languages, caps.MessageTags, caps.MultiPrefix, caps.Rename, caps.Resume, caps.ServerTime, caps.UserhostInNames)
  14. // CapValues are the actual values we advertise to v3.2 clients.
  15. // actual values are set during server startup.
  16. CapValues = caps.NewValues()
  17. )
  18. // CapState shows whether we're negotiating caps, finished, etc for connection registration.
  19. type CapState uint
  20. const (
  21. // CapNone means CAP hasn't been negotiated at all.
  22. CapNone CapState = iota
  23. // CapNegotiating means CAP is being negotiated and registration should be paused.
  24. CapNegotiating CapState = iota
  25. // CapNegotiated means CAP negotiation has been successfully ended and reg should complete.
  26. CapNegotiated CapState = iota
  27. )
  28. // CAP <subcmd> [<caps>]
  29. func capHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
  30. subCommand := strings.ToUpper(msg.Params[0])
  31. capabilities := caps.NewSet()
  32. var capString string
  33. if len(msg.Params) > 1 {
  34. capString = msg.Params[1]
  35. strs := strings.Split(capString, " ")
  36. for _, str := range strs {
  37. if len(str) > 0 {
  38. capabilities.Enable(caps.Capability(str))
  39. }
  40. }
  41. }
  42. switch subCommand {
  43. case "LS":
  44. if !client.registered {
  45. client.capState = CapNegotiating
  46. }
  47. if len(msg.Params) > 1 && msg.Params[1] == "302" {
  48. client.capVersion = 302
  49. }
  50. // weechat 1.4 has a bug here where it won't accept the CAP reply unless it contains
  51. // the server.name source... otherwise it doesn't respond to the CAP message with
  52. // anything and just hangs on connection.
  53. //TODO(dan): limit number of caps and send it multiline in 3.2 style as appropriate.
  54. client.Send(nil, server.name, "CAP", client.nick, subCommand, SupportedCapabilities.String(client.capVersion, CapValues))
  55. case "LIST":
  56. client.Send(nil, server.name, "CAP", client.nick, subCommand, client.capabilities.String(caps.Cap301, CapValues)) // values not sent on LIST so force 3.1
  57. case "REQ":
  58. if !client.registered {
  59. client.capState = CapNegotiating
  60. }
  61. // make sure all capabilities actually exist
  62. for _, capability := range capabilities.List() {
  63. if !SupportedCapabilities.Has(capability) {
  64. client.Send(nil, server.name, "CAP", client.nick, "NAK", capString)
  65. return false
  66. }
  67. }
  68. client.capabilities.Enable(capabilities.List()...)
  69. client.Send(nil, server.name, "CAP", client.nick, "ACK", capString)
  70. case "END":
  71. if !client.registered {
  72. client.capState = CapNegotiated
  73. server.tryRegister(client)
  74. }
  75. default:
  76. client.Send(nil, server.name, ERR_INVALIDCAPCMD, client.nick, subCommand, client.t("Invalid CAP subcommand"))
  77. }
  78. return false
  79. }