Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

set.go 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package caps
  4. import (
  5. "fmt"
  6. "github.com/ergochat/ergo/irc/utils"
  7. )
  8. // Set holds a set of enabled capabilities.
  9. type Set [bitsetLen]uint32
  10. // Values holds capability values.
  11. type Values map[Capability]string
  12. // NewSet returns a new Set, with the given capabilities enabled.
  13. func NewSet(capabs ...Capability) *Set {
  14. var newSet Set
  15. newSet.Enable(capabs...)
  16. return &newSet
  17. }
  18. // NewCompleteSet returns a new Set, with all defined capabilities enabled.
  19. func NewCompleteSet() *Set {
  20. var newSet Set
  21. asSlice := newSet[:]
  22. for i := 0; i < numCapabs; i += 1 {
  23. utils.BitsetSet(asSlice, uint(i), true)
  24. }
  25. return &newSet
  26. }
  27. // Enable enables the given capabilities.
  28. func (s *Set) Enable(capabs ...Capability) {
  29. asSlice := s[:]
  30. for _, capab := range capabs {
  31. utils.BitsetSet(asSlice, uint(capab), true)
  32. }
  33. }
  34. // Disable disables the given capabilities.
  35. func (s *Set) Disable(capabs ...Capability) {
  36. asSlice := s[:]
  37. for _, capab := range capabs {
  38. utils.BitsetSet(asSlice, uint(capab), false)
  39. }
  40. }
  41. // Add adds the given capabilities to this set.
  42. // this is just a wrapper to allow more clear use.
  43. func (s *Set) Add(capabs ...Capability) {
  44. s.Enable(capabs...)
  45. }
  46. // Remove removes the given capabilities from this set.
  47. // this is just a wrapper to allow more clear use.
  48. func (s *Set) Remove(capabs ...Capability) {
  49. s.Disable(capabs...)
  50. }
  51. // Has returns true if this set has the given capability.
  52. func (s *Set) Has(capab Capability) bool {
  53. return utils.BitsetGet(s[:], uint(capab))
  54. }
  55. // HasAll returns true if the set has all the given capabilities.
  56. func (s *Set) HasAll(capabs ...Capability) bool {
  57. for _, capab := range capabs {
  58. if !s.Has(capab) {
  59. return false
  60. }
  61. }
  62. return true
  63. }
  64. // Union adds all the capabilities of another set to this set.
  65. func (s *Set) Union(other *Set) {
  66. utils.BitsetUnion(s[:], other[:])
  67. }
  68. // Subtract removes all the capabilities of another set from this set.
  69. func (s *Set) Subtract(other *Set) {
  70. utils.BitsetSubtract(s[:], other[:])
  71. }
  72. // Empty returns whether the set is empty.
  73. func (s *Set) Empty() bool {
  74. return utils.BitsetEmpty(s[:])
  75. }
  76. const defaultMaxPayloadLength = 450
  77. // Strings returns all of our enabled capabilities as a slice of strings.
  78. func (s *Set) Strings(version Version, values Values, maxLen int) (result []string) {
  79. if maxLen == 0 {
  80. maxLen = defaultMaxPayloadLength
  81. }
  82. var t utils.TokenLineBuilder
  83. t.Initialize(maxLen, " ")
  84. var capab Capability
  85. asSlice := s[:]
  86. for capab = 0; capab < numCapabs; capab++ {
  87. // XXX clients that only support CAP LS 301 cannot handle multiline
  88. // responses. omit some CAPs in this case, forcing the response to fit on
  89. // a single line. this is technically buggy for CAP LIST (as opposed to LS)
  90. // but it shouldn't matter
  91. if version < Cap302 && !isAllowed301(capab) {
  92. continue
  93. }
  94. // skip any capabilities that are not enabled
  95. if !utils.BitsetGet(asSlice, uint(capab)) {
  96. continue
  97. }
  98. capString := capab.Name()
  99. if version >= Cap302 {
  100. val, exists := values[capab]
  101. if exists {
  102. capString = fmt.Sprintf("%s=%s", capString, val)
  103. }
  104. }
  105. t.Add(capString)
  106. }
  107. result = t.Lines()
  108. if result == nil {
  109. result = []string{""}
  110. }
  111. return
  112. }
  113. // this is a fixed whitelist of caps that are eligible for display in CAP LS 301
  114. func isAllowed301(capab Capability) bool {
  115. switch capab {
  116. case AccountNotify, AccountTag, AwayNotify, Batch, ChgHost, Chathistory, EventPlayback,
  117. Relaymsg, EchoMessage, Nope, ExtendedJoin, InviteNotify, LabeledResponse, MessageTags,
  118. MultiPrefix, SASL, ServerTime, SetName, STS, UserhostInNames, ZNCSelfMessage, ZNCPlayback:
  119. return true
  120. default:
  121. return false
  122. }
  123. }