You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

channel.go 41KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296
  1. // Copyright (c) 2012-2014 Jeremy Latt
  2. // Copyright (c) 2014-2015 Edmund Huber
  3. // Copyright (c) 2016-2017 Daniel Oaks <daniel@danieloaks.net>
  4. // released under the MIT license
  5. package irc
  6. import (
  7. "bytes"
  8. "fmt"
  9. "strconv"
  10. "strings"
  11. "time"
  12. "sync"
  13. "github.com/oragono/oragono/irc/caps"
  14. "github.com/oragono/oragono/irc/history"
  15. "github.com/oragono/oragono/irc/modes"
  16. "github.com/oragono/oragono/irc/utils"
  17. )
  18. const (
  19. histServMask = "HistServ!HistServ@localhost"
  20. )
  21. // Channel represents a channel that clients can join.
  22. type Channel struct {
  23. flags modes.ModeSet
  24. lists map[modes.Mode]*UserMaskSet
  25. key string
  26. members MemberSet
  27. membersCache []*Client // allow iteration over channel members without holding the lock
  28. name string
  29. nameCasefolded string
  30. server *Server
  31. createdTime time.Time
  32. registeredFounder string
  33. registeredTime time.Time
  34. transferPendingTo string
  35. topic string
  36. topicSetBy string
  37. topicSetTime time.Time
  38. userLimit int
  39. accountToUMode map[string]modes.Mode
  40. history history.Buffer
  41. stateMutex sync.RWMutex // tier 1
  42. writerSemaphore utils.Semaphore // tier 1.5
  43. joinPartMutex sync.Mutex // tier 3
  44. ensureLoaded utils.Once // manages loading stored registration info from the database
  45. dirtyBits uint
  46. }
  47. // NewChannel creates a new channel from a `Server` and a `name`
  48. // string, which must be unique on the server.
  49. func NewChannel(s *Server, name, casefoldedName string, registered bool) *Channel {
  50. config := s.Config()
  51. channel := &Channel{
  52. createdTime: time.Now().UTC(), // may be overwritten by applyRegInfo
  53. members: make(MemberSet),
  54. name: name,
  55. nameCasefolded: casefoldedName,
  56. server: s,
  57. }
  58. channel.initializeLists()
  59. channel.writerSemaphore.Initialize(1)
  60. channel.history.Initialize(config.History.ChannelLength, config.History.AutoresizeWindow)
  61. if !registered {
  62. for _, mode := range config.Channels.defaultModes {
  63. channel.flags.SetMode(mode, true)
  64. }
  65. // no loading to do, so "mark" the load operation as "done":
  66. channel.ensureLoaded.Do(func() {})
  67. } // else: modes will be loaded before first join
  68. return channel
  69. }
  70. func (channel *Channel) initializeLists() {
  71. channel.lists = map[modes.Mode]*UserMaskSet{
  72. modes.BanMask: NewUserMaskSet(),
  73. modes.ExceptMask: NewUserMaskSet(),
  74. modes.InviteMask: NewUserMaskSet(),
  75. }
  76. channel.accountToUMode = make(map[string]modes.Mode)
  77. }
  78. // EnsureLoaded blocks until the channel's registration info has been loaded
  79. // from the database.
  80. func (channel *Channel) EnsureLoaded() {
  81. channel.ensureLoaded.Do(func() {
  82. nmc := channel.NameCasefolded()
  83. info, err := channel.server.channelRegistry.LoadChannel(nmc)
  84. if err == nil {
  85. channel.applyRegInfo(info)
  86. } else {
  87. channel.server.logger.Error("internal", "couldn't load channel", nmc, err.Error())
  88. }
  89. })
  90. }
  91. func (channel *Channel) IsLoaded() bool {
  92. return channel.ensureLoaded.Done()
  93. }
  94. // read in channel state that was persisted in the DB
  95. func (channel *Channel) applyRegInfo(chanReg RegisteredChannel) {
  96. channel.stateMutex.Lock()
  97. defer channel.stateMutex.Unlock()
  98. channel.registeredFounder = chanReg.Founder
  99. channel.registeredTime = chanReg.RegisteredAt
  100. channel.topic = chanReg.Topic
  101. channel.topicSetBy = chanReg.TopicSetBy
  102. channel.topicSetTime = chanReg.TopicSetTime
  103. channel.name = chanReg.Name
  104. channel.createdTime = chanReg.RegisteredAt
  105. channel.key = chanReg.Key
  106. for _, mode := range chanReg.Modes {
  107. channel.flags.SetMode(mode, true)
  108. }
  109. for account, mode := range chanReg.AccountToUMode {
  110. channel.accountToUMode[account] = mode
  111. }
  112. channel.lists[modes.BanMask].SetMasks(chanReg.Bans)
  113. channel.lists[modes.InviteMask].SetMasks(chanReg.Invites)
  114. channel.lists[modes.ExceptMask].SetMasks(chanReg.Excepts)
  115. }
  116. // obtain a consistent snapshot of the channel state that can be persisted to the DB
  117. func (channel *Channel) ExportRegistration(includeFlags uint) (info RegisteredChannel) {
  118. channel.stateMutex.RLock()
  119. defer channel.stateMutex.RUnlock()
  120. info.Name = channel.name
  121. info.NameCasefolded = channel.nameCasefolded
  122. info.Founder = channel.registeredFounder
  123. info.RegisteredAt = channel.registeredTime
  124. if includeFlags&IncludeTopic != 0 {
  125. info.Topic = channel.topic
  126. info.TopicSetBy = channel.topicSetBy
  127. info.TopicSetTime = channel.topicSetTime
  128. }
  129. if includeFlags&IncludeModes != 0 {
  130. info.Key = channel.key
  131. info.Modes = channel.flags.AllModes()
  132. }
  133. if includeFlags&IncludeLists != 0 {
  134. info.Bans = channel.lists[modes.BanMask].Masks()
  135. info.Invites = channel.lists[modes.InviteMask].Masks()
  136. info.Excepts = channel.lists[modes.ExceptMask].Masks()
  137. info.AccountToUMode = make(map[string]modes.Mode)
  138. for account, mode := range channel.accountToUMode {
  139. info.AccountToUMode[account] = mode
  140. }
  141. }
  142. return
  143. }
  144. // begin: asynchronous database writeback implementation, modeled on irc/socket.go
  145. // MarkDirty marks part (or all) of a channel's data as needing to be written back
  146. // to the database, then starts a writer goroutine if necessary.
  147. // This is the equivalent of Socket.Write().
  148. func (channel *Channel) MarkDirty(dirtyBits uint) {
  149. channel.stateMutex.Lock()
  150. isRegistered := channel.registeredFounder != ""
  151. channel.dirtyBits = channel.dirtyBits | dirtyBits
  152. channel.stateMutex.Unlock()
  153. if !isRegistered {
  154. return
  155. }
  156. channel.wakeWriter()
  157. }
  158. // IsClean returns whether a channel can be safely removed from the server.
  159. // To avoid the obvious TOCTOU race condition, it must be called while holding
  160. // ChannelManager's lock (that way, no one can join and make the channel dirty again
  161. // between this method exiting and the actual deletion).
  162. func (channel *Channel) IsClean() bool {
  163. if !channel.writerSemaphore.TryAcquire() {
  164. // a database write (which may fail) is in progress, the channel cannot be cleaned up
  165. return false
  166. }
  167. defer channel.writerSemaphore.Release()
  168. channel.stateMutex.RLock()
  169. defer channel.stateMutex.RUnlock()
  170. // the channel must be empty, and either be unregistered or fully written to the DB
  171. return len(channel.members) == 0 && (channel.registeredFounder == "" || channel.dirtyBits == 0)
  172. }
  173. func (channel *Channel) wakeWriter() {
  174. if channel.writerSemaphore.TryAcquire() {
  175. go channel.writeLoop()
  176. }
  177. }
  178. // equivalent of Socket.send()
  179. func (channel *Channel) writeLoop() {
  180. for {
  181. // TODO(#357) check the error value of this and implement timed backoff
  182. channel.performWrite(0)
  183. channel.writerSemaphore.Release()
  184. channel.stateMutex.RLock()
  185. isDirty := channel.dirtyBits != 0
  186. isEmpty := len(channel.members) == 0
  187. channel.stateMutex.RUnlock()
  188. if !isDirty {
  189. if isEmpty {
  190. channel.server.channels.Cleanup(channel)
  191. }
  192. return // nothing to do
  193. } // else: isDirty, so we need to write again
  194. if !channel.writerSemaphore.TryAcquire() {
  195. return
  196. }
  197. }
  198. }
  199. // Store writes part (or all) of the channel's data back to the database,
  200. // blocking until the write is complete. This is the equivalent of
  201. // Socket.BlockingWrite.
  202. func (channel *Channel) Store(dirtyBits uint) (err error) {
  203. defer func() {
  204. channel.stateMutex.Lock()
  205. isDirty := channel.dirtyBits != 0
  206. isEmpty := len(channel.members) == 0
  207. channel.stateMutex.Unlock()
  208. if isDirty {
  209. channel.wakeWriter()
  210. } else if isEmpty {
  211. channel.server.channels.Cleanup(channel)
  212. }
  213. }()
  214. channel.writerSemaphore.Acquire()
  215. defer channel.writerSemaphore.Release()
  216. return channel.performWrite(dirtyBits)
  217. }
  218. // do an individual write; equivalent of Socket.send()
  219. func (channel *Channel) performWrite(additionalDirtyBits uint) (err error) {
  220. channel.stateMutex.Lock()
  221. dirtyBits := channel.dirtyBits | additionalDirtyBits
  222. channel.dirtyBits = 0
  223. isRegistered := channel.registeredFounder != ""
  224. channel.stateMutex.Unlock()
  225. if !isRegistered || dirtyBits == 0 {
  226. return
  227. }
  228. info := channel.ExportRegistration(dirtyBits)
  229. err = channel.server.channelRegistry.StoreChannel(info, dirtyBits)
  230. if err != nil {
  231. channel.stateMutex.Lock()
  232. channel.dirtyBits = channel.dirtyBits | dirtyBits
  233. channel.stateMutex.Unlock()
  234. }
  235. return
  236. }
  237. // SetRegistered registers the channel, returning an error if it was already registered.
  238. func (channel *Channel) SetRegistered(founder string) error {
  239. channel.stateMutex.Lock()
  240. defer channel.stateMutex.Unlock()
  241. if channel.registeredFounder != "" {
  242. return errChannelAlreadyRegistered
  243. }
  244. channel.registeredFounder = founder
  245. channel.registeredTime = time.Now().UTC()
  246. channel.accountToUMode[founder] = modes.ChannelFounder
  247. return nil
  248. }
  249. // SetUnregistered deletes the channel's registration information.
  250. func (channel *Channel) SetUnregistered(expectedFounder string) {
  251. channel.stateMutex.Lock()
  252. defer channel.stateMutex.Unlock()
  253. if channel.registeredFounder != expectedFounder {
  254. return
  255. }
  256. channel.registeredFounder = ""
  257. var zeroTime time.Time
  258. channel.registeredTime = zeroTime
  259. channel.accountToUMode = make(map[string]modes.Mode)
  260. }
  261. // implements `CHANSERV CLEAR #chan ACCESS` (resets bans, invites, excepts, and amodes)
  262. func (channel *Channel) resetAccess() {
  263. defer channel.MarkDirty(IncludeLists)
  264. channel.stateMutex.Lock()
  265. defer channel.stateMutex.Unlock()
  266. channel.initializeLists()
  267. if channel.registeredFounder != "" {
  268. channel.accountToUMode[channel.registeredFounder] = modes.ChannelFounder
  269. }
  270. }
  271. // IsRegistered returns whether the channel is registered.
  272. func (channel *Channel) IsRegistered() bool {
  273. channel.stateMutex.RLock()
  274. defer channel.stateMutex.RUnlock()
  275. return channel.registeredFounder != ""
  276. }
  277. type channelTransferStatus uint
  278. const (
  279. channelTransferComplete channelTransferStatus = iota
  280. channelTransferPending
  281. channelTransferCancelled
  282. channelTransferFailed
  283. )
  284. // Transfer transfers ownership of a registered channel to a different account
  285. func (channel *Channel) Transfer(client *Client, target string, hasPrivs bool) (status channelTransferStatus, err error) {
  286. status = channelTransferFailed
  287. defer func() {
  288. if status == channelTransferComplete && err == nil {
  289. channel.Store(IncludeAllChannelAttrs)
  290. }
  291. }()
  292. cftarget, err := CasefoldName(target)
  293. if err != nil {
  294. err = errAccountDoesNotExist
  295. return
  296. }
  297. channel.stateMutex.Lock()
  298. defer channel.stateMutex.Unlock()
  299. if channel.registeredFounder == "" {
  300. err = errChannelNotOwnedByAccount
  301. return
  302. }
  303. if hasPrivs {
  304. channel.transferOwnership(cftarget)
  305. return channelTransferComplete, nil
  306. } else {
  307. if channel.registeredFounder == cftarget {
  308. // transferring back to yourself cancels a pending transfer
  309. channel.transferPendingTo = ""
  310. return channelTransferCancelled, nil
  311. } else {
  312. channel.transferPendingTo = cftarget
  313. return channelTransferPending, nil
  314. }
  315. }
  316. }
  317. func (channel *Channel) transferOwnership(newOwner string) {
  318. delete(channel.accountToUMode, channel.registeredFounder)
  319. channel.registeredFounder = newOwner
  320. channel.accountToUMode[channel.registeredFounder] = modes.ChannelFounder
  321. channel.transferPendingTo = ""
  322. }
  323. // AcceptTransfer implements `CS TRANSFER #chan ACCEPT`
  324. func (channel *Channel) AcceptTransfer(client *Client) (err error) {
  325. defer func() {
  326. if err == nil {
  327. channel.Store(IncludeAllChannelAttrs)
  328. }
  329. }()
  330. account := client.Account()
  331. if account == "" {
  332. return errAccountNotLoggedIn
  333. }
  334. channel.stateMutex.Lock()
  335. defer channel.stateMutex.Unlock()
  336. if account != channel.transferPendingTo {
  337. return errChannelTransferNotOffered
  338. }
  339. channel.transferOwnership(account)
  340. return nil
  341. }
  342. func (channel *Channel) regenerateMembersCache() {
  343. channel.stateMutex.RLock()
  344. result := make([]*Client, len(channel.members))
  345. i := 0
  346. for client := range channel.members {
  347. result[i] = client
  348. i++
  349. }
  350. channel.stateMutex.RUnlock()
  351. channel.stateMutex.Lock()
  352. channel.membersCache = result
  353. channel.stateMutex.Unlock()
  354. }
  355. // Names sends the list of users joined to the channel to the given client.
  356. func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
  357. isJoined := channel.hasClient(client)
  358. isOper := client.HasMode(modes.Operator)
  359. isMultiPrefix := rb.session.capabilities.Has(caps.MultiPrefix)
  360. isUserhostInNames := rb.session.capabilities.Has(caps.UserhostInNames)
  361. maxNamLen := 480 - len(client.server.name) - len(client.Nick())
  362. var namesLines []string
  363. var buffer bytes.Buffer
  364. if isJoined || !channel.flags.HasMode(modes.Secret) || isOper {
  365. for _, target := range channel.Members() {
  366. var nick string
  367. if isUserhostInNames {
  368. nick = target.NickMaskString()
  369. } else {
  370. nick = target.Nick()
  371. }
  372. channel.stateMutex.RLock()
  373. modeSet := channel.members[target]
  374. channel.stateMutex.RUnlock()
  375. if modeSet == nil {
  376. continue
  377. }
  378. if !isJoined && target.flags.HasMode(modes.Invisible) && !isOper {
  379. continue
  380. }
  381. prefix := modeSet.Prefixes(isMultiPrefix)
  382. if buffer.Len()+len(nick)+len(prefix)+1 > maxNamLen {
  383. namesLines = append(namesLines, buffer.String())
  384. buffer.Reset()
  385. }
  386. if buffer.Len() > 0 {
  387. buffer.WriteString(" ")
  388. }
  389. buffer.WriteString(prefix)
  390. buffer.WriteString(nick)
  391. }
  392. if buffer.Len() > 0 {
  393. namesLines = append(namesLines, buffer.String())
  394. }
  395. }
  396. for _, line := range namesLines {
  397. if buffer.Len() > 0 {
  398. rb.Add(nil, client.server.name, RPL_NAMREPLY, client.nick, "=", channel.name, line)
  399. }
  400. }
  401. rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
  402. }
  403. // does `clientMode` give you privileges to grant/remove `targetMode` to/from people,
  404. // or to kick them?
  405. func channelUserModeHasPrivsOver(clientMode modes.Mode, targetMode modes.Mode) bool {
  406. switch clientMode {
  407. case modes.ChannelFounder:
  408. return true
  409. case modes.ChannelAdmin, modes.ChannelOperator:
  410. // admins cannot kick other admins, operators *can* kick other operators
  411. return targetMode != modes.ChannelFounder && targetMode != modes.ChannelAdmin
  412. case modes.Halfop:
  413. // halfops cannot kick other halfops
  414. return targetMode == modes.Voice || targetMode == modes.Mode(0)
  415. default:
  416. // voice and unprivileged cannot kick anyone
  417. return false
  418. }
  419. }
  420. // ClientIsAtLeast returns whether the client has at least the given channel privilege.
  421. func (channel *Channel) ClientIsAtLeast(client *Client, permission modes.Mode) bool {
  422. channel.stateMutex.RLock()
  423. clientModes := channel.members[client]
  424. channel.stateMutex.RUnlock()
  425. for _, mode := range modes.ChannelUserModes {
  426. if clientModes.HasMode(mode) {
  427. return true
  428. }
  429. if mode == permission {
  430. break
  431. }
  432. }
  433. return false
  434. }
  435. func (channel *Channel) ClientPrefixes(client *Client, isMultiPrefix bool) string {
  436. channel.stateMutex.RLock()
  437. defer channel.stateMutex.RUnlock()
  438. modes, present := channel.members[client]
  439. if !present {
  440. return ""
  441. } else {
  442. return modes.Prefixes(isMultiPrefix)
  443. }
  444. }
  445. func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool {
  446. channel.stateMutex.RLock()
  447. clientModes := channel.members[client]
  448. targetModes := channel.members[target]
  449. channel.stateMutex.RUnlock()
  450. return channelUserModeHasPrivsOver(clientModes.HighestChannelUserMode(), targetModes.HighestChannelUserMode())
  451. }
  452. func (channel *Channel) hasClient(client *Client) bool {
  453. channel.stateMutex.RLock()
  454. _, present := channel.members[client]
  455. channel.stateMutex.RUnlock()
  456. return present
  457. }
  458. // <mode> <mode params>
  459. func (channel *Channel) modeStrings(client *Client) (result []string) {
  460. isMember := client.HasMode(modes.Operator) || channel.hasClient(client)
  461. showKey := isMember && (channel.key != "")
  462. showUserLimit := channel.userLimit > 0
  463. mods := "+"
  464. // flags with args
  465. if showKey {
  466. mods += modes.Key.String()
  467. }
  468. if showUserLimit {
  469. mods += modes.UserLimit.String()
  470. }
  471. mods += channel.flags.String()
  472. channel.stateMutex.RLock()
  473. defer channel.stateMutex.RUnlock()
  474. result = []string{mods}
  475. // args for flags with args: The order must match above to keep
  476. // positional arguments in place.
  477. if showKey {
  478. result = append(result, channel.key)
  479. }
  480. if showUserLimit {
  481. result = append(result, strconv.Itoa(channel.userLimit))
  482. }
  483. return
  484. }
  485. func (channel *Channel) IsEmpty() bool {
  486. channel.stateMutex.RLock()
  487. defer channel.stateMutex.RUnlock()
  488. return len(channel.members) == 0
  489. }
  490. // Join joins the given client to this channel (if they can be joined).
  491. func (channel *Channel) Join(client *Client, key string, isSajoin bool, rb *ResponseBuffer) {
  492. details := client.Details()
  493. channel.stateMutex.RLock()
  494. chname := channel.name
  495. chcfname := channel.nameCasefolded
  496. founder := channel.registeredFounder
  497. chkey := channel.key
  498. limit := channel.userLimit
  499. chcount := len(channel.members)
  500. _, alreadyJoined := channel.members[client]
  501. persistentMode := channel.accountToUMode[details.account]
  502. channel.stateMutex.RUnlock()
  503. if alreadyJoined {
  504. // no message needs to be sent
  505. return
  506. }
  507. // the founder can always join (even if they disabled auto +q on join);
  508. // anyone who automatically receives halfop or higher can always join
  509. hasPrivs := isSajoin || (founder != "" && founder == details.account) || (persistentMode != 0 && persistentMode != modes.Voice)
  510. if !hasPrivs && limit != 0 && chcount >= limit {
  511. rb.Add(nil, client.server.name, ERR_CHANNELISFULL, details.nick, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "l"))
  512. return
  513. }
  514. if !hasPrivs && chkey != "" && !utils.SecretTokensMatch(chkey, key) {
  515. rb.Add(nil, client.server.name, ERR_BADCHANNELKEY, details.nick, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "k"))
  516. return
  517. }
  518. isInvited := client.CheckInvited(chcfname) || channel.lists[modes.InviteMask].Match(details.nickMaskCasefolded)
  519. if !hasPrivs && channel.flags.HasMode(modes.InviteOnly) && !isInvited {
  520. rb.Add(nil, client.server.name, ERR_INVITEONLYCHAN, details.nick, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "i"))
  521. return
  522. }
  523. if !hasPrivs && channel.lists[modes.BanMask].Match(details.nickMaskCasefolded) &&
  524. !isInvited &&
  525. !channel.lists[modes.ExceptMask].Match(details.nickMaskCasefolded) {
  526. rb.Add(nil, client.server.name, ERR_BANNEDFROMCHAN, details.nick, chname, fmt.Sprintf(client.t("Cannot join channel (+%s)"), "b"))
  527. return
  528. }
  529. if !hasPrivs && channel.flags.HasMode(modes.RegisteredOnly) && details.account == "" && !isInvited {
  530. rb.Add(nil, client.server.name, ERR_BANNEDFROMCHAN, details.nick, chname, client.t("You must be registered to join that channel"))
  531. return
  532. }
  533. client.server.logger.Debug("join", fmt.Sprintf("%s joined channel %s", details.nick, chname))
  534. var message utils.SplitMessage
  535. givenMode := func() (givenMode modes.Mode) {
  536. channel.joinPartMutex.Lock()
  537. defer channel.joinPartMutex.Unlock()
  538. func() {
  539. channel.stateMutex.Lock()
  540. defer channel.stateMutex.Unlock()
  541. channel.members.Add(client)
  542. firstJoin := len(channel.members) == 1
  543. newChannel := firstJoin && channel.registeredFounder == ""
  544. if newChannel {
  545. givenMode = modes.ChannelOperator
  546. } else {
  547. givenMode = persistentMode
  548. }
  549. if givenMode != 0 {
  550. channel.members[client].SetMode(givenMode, true)
  551. }
  552. }()
  553. channel.regenerateMembersCache()
  554. message = utils.MakeSplitMessage("", true)
  555. histItem := history.Item{
  556. Type: history.Join,
  557. Nick: details.nickMask,
  558. AccountName: details.accountName,
  559. Message: message,
  560. }
  561. histItem.Params[0] = details.realname
  562. channel.history.Add(histItem)
  563. return
  564. }()
  565. client.addChannel(channel)
  566. var modestr string
  567. if givenMode != 0 {
  568. modestr = fmt.Sprintf("+%v", givenMode)
  569. }
  570. for _, member := range channel.Members() {
  571. for _, session := range member.Sessions() {
  572. if session == rb.session {
  573. continue
  574. } else if client == session.client {
  575. channel.playJoinForSession(session)
  576. continue
  577. }
  578. if session.capabilities.Has(caps.ExtendedJoin) {
  579. session.sendFromClientInternal(false, message.Time, message.Msgid, details.nickMask, details.accountName, nil, "JOIN", chname, details.accountName, details.realname)
  580. } else {
  581. session.sendFromClientInternal(false, message.Time, message.Msgid, details.nickMask, details.accountName, nil, "JOIN", chname)
  582. }
  583. if givenMode != 0 {
  584. session.Send(nil, client.server.name, "MODE", chname, modestr, details.nick)
  585. }
  586. }
  587. }
  588. if rb.session.capabilities.Has(caps.ExtendedJoin) {
  589. rb.AddFromClient(message.Time, message.Msgid, details.nickMask, details.accountName, nil, "JOIN", chname, details.accountName, details.realname)
  590. } else {
  591. rb.AddFromClient(message.Time, message.Msgid, details.nickMask, details.accountName, nil, "JOIN", chname)
  592. }
  593. if rb.session.client == client {
  594. // don't send topic and names for a SAJOIN of a different client
  595. channel.SendTopic(client, rb, false)
  596. channel.Names(client, rb)
  597. }
  598. // TODO #259 can be implemented as Flush(false) (i.e., nonblocking) while holding joinPartMutex
  599. rb.Flush(true)
  600. channel.autoReplayHistory(client, rb, message.Msgid)
  601. }
  602. func (channel *Channel) autoReplayHistory(client *Client, rb *ResponseBuffer, skipMsgid string) {
  603. // autoreplay any messages as necessary
  604. config := channel.server.Config()
  605. var items []history.Item
  606. if rb.session.zncPlaybackTimes != nil && (rb.session.zncPlaybackTimes.targets == nil || rb.session.zncPlaybackTimes.targets[channel.NameCasefolded()]) {
  607. items, _ = channel.history.Between(rb.session.zncPlaybackTimes.after, rb.session.zncPlaybackTimes.before, false, config.History.ChathistoryMax)
  608. } else if !rb.session.HasHistoryCaps() {
  609. var replayLimit int
  610. customReplayLimit := client.AccountSettings().AutoreplayLines
  611. if customReplayLimit != nil {
  612. replayLimit = *customReplayLimit
  613. maxLimit := channel.server.Config().History.ChathistoryMax
  614. if maxLimit < replayLimit {
  615. replayLimit = maxLimit
  616. }
  617. } else {
  618. replayLimit = channel.server.Config().History.AutoreplayOnJoin
  619. }
  620. if 0 < replayLimit {
  621. items = channel.history.Latest(replayLimit)
  622. }
  623. }
  624. // remove the client's own JOIN line from the replay
  625. numItems := len(items)
  626. for i := len(items) - 1; 0 <= i; i-- {
  627. if items[i].Message.Msgid == skipMsgid {
  628. // zero'ed items will not be replayed because their `Type` field is not recognized
  629. items[i] = history.Item{}
  630. numItems--
  631. break
  632. }
  633. }
  634. if 0 < numItems {
  635. channel.replayHistoryItems(rb, items, true)
  636. rb.Flush(true)
  637. }
  638. }
  639. // plays channel join messages (the JOIN line, topic, and names) to a session.
  640. // this is used when attaching a new session to an existing client that already has
  641. // channels, and also when one session of a client initiates a JOIN and the other
  642. // sessions need to receive the state change
  643. func (channel *Channel) playJoinForSession(session *Session) {
  644. client := session.client
  645. sessionRb := NewResponseBuffer(session)
  646. details := client.Details()
  647. if session.capabilities.Has(caps.ExtendedJoin) {
  648. sessionRb.Add(nil, details.nickMask, "JOIN", channel.Name(), details.accountName, details.realname)
  649. } else {
  650. sessionRb.Add(nil, details.nickMask, "JOIN", channel.Name())
  651. }
  652. channel.SendTopic(client, sessionRb, false)
  653. channel.Names(client, sessionRb)
  654. sessionRb.Send(false)
  655. }
  656. // Part parts the given client from this channel, with the given message.
  657. func (channel *Channel) Part(client *Client, message string, rb *ResponseBuffer) {
  658. chname := channel.Name()
  659. if !channel.hasClient(client) {
  660. rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, client.Nick(), chname, client.t("You're not on that channel"))
  661. return
  662. }
  663. channel.Quit(client)
  664. splitMessage := utils.MakeSplitMessage(message, true)
  665. details := client.Details()
  666. params := make([]string, 1, 2)
  667. params[0] = chname
  668. if message != "" {
  669. params = append(params, message)
  670. }
  671. for _, member := range channel.Members() {
  672. member.sendFromClientInternal(false, splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
  673. }
  674. rb.AddFromClient(splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
  675. for _, session := range client.Sessions() {
  676. if session != rb.session {
  677. session.sendFromClientInternal(false, splitMessage.Time, splitMessage.Msgid, details.nickMask, details.accountName, nil, "PART", params...)
  678. }
  679. }
  680. channel.history.Add(history.Item{
  681. Type: history.Part,
  682. Nick: details.nickMask,
  683. AccountName: details.accountName,
  684. Message: splitMessage,
  685. })
  686. client.server.logger.Debug("part", fmt.Sprintf("%s left channel %s", details.nick, chname))
  687. }
  688. // Resume is called after a successful global resume to:
  689. // 1. Replace the old client with the new in the channel's data structures
  690. // 2. Send JOIN and MODE lines to channel participants (including the new client)
  691. // 3. Replay missed message history to the client
  692. func (channel *Channel) Resume(session *Session, timestamp time.Time) {
  693. now := time.Now().UTC()
  694. channel.resumeAndAnnounce(session)
  695. if !timestamp.IsZero() {
  696. channel.replayHistoryForResume(session, timestamp, now)
  697. }
  698. }
  699. func (channel *Channel) resumeAndAnnounce(session *Session) {
  700. channel.stateMutex.RLock()
  701. modeSet := channel.members[session.client]
  702. channel.stateMutex.RUnlock()
  703. if modeSet == nil {
  704. return
  705. }
  706. oldModes := modeSet.String()
  707. if 0 < len(oldModes) {
  708. oldModes = "+" + oldModes
  709. }
  710. // send join for old clients
  711. chname := channel.Name()
  712. details := session.client.Details()
  713. for _, member := range channel.Members() {
  714. for _, session := range member.Sessions() {
  715. if session.capabilities.Has(caps.Resume) {
  716. continue
  717. }
  718. if session.capabilities.Has(caps.ExtendedJoin) {
  719. session.Send(nil, details.nickMask, "JOIN", chname, details.accountName, details.realname)
  720. } else {
  721. session.Send(nil, details.nickMask, "JOIN", chname)
  722. }
  723. if 0 < len(oldModes) {
  724. session.Send(nil, channel.server.name, "MODE", chname, oldModes, details.nick)
  725. }
  726. }
  727. }
  728. rb := NewResponseBuffer(session)
  729. // use blocking i/o to synchronize with the later history replay
  730. if rb.session.capabilities.Has(caps.ExtendedJoin) {
  731. rb.Add(nil, details.nickMask, "JOIN", channel.name, details.accountName, details.realname)
  732. } else {
  733. rb.Add(nil, details.nickMask, "JOIN", channel.name)
  734. }
  735. channel.SendTopic(session.client, rb, false)
  736. channel.Names(session.client, rb)
  737. rb.Send(true)
  738. }
  739. func (channel *Channel) replayHistoryForResume(session *Session, after time.Time, before time.Time) {
  740. items, complete := channel.history.Between(after, before, false, 0)
  741. rb := NewResponseBuffer(session)
  742. channel.replayHistoryItems(rb, items, false)
  743. if !complete && !session.resumeDetails.HistoryIncomplete {
  744. // warn here if we didn't warn already
  745. rb.Add(nil, histServMask, "NOTICE", channel.Name(), session.client.t("Some additional message history may have been lost"))
  746. }
  747. rb.Send(true)
  748. }
  749. func stripMaskFromNick(nickMask string) (nick string) {
  750. index := strings.Index(nickMask, "!")
  751. if index == -1 {
  752. return nickMask
  753. }
  754. return nickMask[0:index]
  755. }
  756. func (channel *Channel) replayHistoryItems(rb *ResponseBuffer, items []history.Item, autoreplay bool) {
  757. if len(items) == 0 {
  758. return
  759. }
  760. chname := channel.Name()
  761. client := rb.target
  762. eventPlayback := rb.session.capabilities.Has(caps.EventPlayback)
  763. extendedJoin := rb.session.capabilities.Has(caps.ExtendedJoin)
  764. var playJoinsAsPrivmsg bool
  765. if !eventPlayback {
  766. switch client.AccountSettings().ReplayJoins {
  767. case ReplayJoinsCommandsOnly:
  768. playJoinsAsPrivmsg = !autoreplay
  769. case ReplayJoinsAlways:
  770. playJoinsAsPrivmsg = true
  771. case ReplayJoinsNever:
  772. playJoinsAsPrivmsg = false
  773. }
  774. }
  775. batchID := rb.StartNestedHistoryBatch(chname)
  776. defer rb.EndNestedBatch(batchID)
  777. for _, item := range items {
  778. nick := stripMaskFromNick(item.Nick)
  779. switch item.Type {
  780. case history.Privmsg:
  781. rb.AddSplitMessageFromClient(item.Nick, item.AccountName, item.Tags, "PRIVMSG", chname, item.Message)
  782. case history.Notice:
  783. rb.AddSplitMessageFromClient(item.Nick, item.AccountName, item.Tags, "NOTICE", chname, item.Message)
  784. case history.Tagmsg:
  785. if rb.session.capabilities.Has(caps.MessageTags) {
  786. rb.AddSplitMessageFromClient(item.Nick, item.AccountName, item.Tags, "TAGMSG", chname, item.Message)
  787. }
  788. case history.Join:
  789. if eventPlayback {
  790. if extendedJoin {
  791. rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "HEVENT", "JOIN", chname, item.AccountName, item.Params[0])
  792. } else {
  793. rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "HEVENT", "JOIN", chname)
  794. }
  795. } else {
  796. if !playJoinsAsPrivmsg {
  797. continue // #474
  798. }
  799. var message string
  800. if item.AccountName == "*" {
  801. message = fmt.Sprintf(client.t("%s joined the channel"), nick)
  802. } else {
  803. message = fmt.Sprintf(client.t("%[1]s [account: %[2]s] joined the channel"), nick, item.AccountName)
  804. }
  805. rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
  806. }
  807. case history.Part:
  808. if eventPlayback {
  809. rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "HEVENT", "PART", chname, item.Message.Message)
  810. } else {
  811. if !playJoinsAsPrivmsg {
  812. continue // #474
  813. }
  814. message := fmt.Sprintf(client.t("%[1]s left the channel (%[2]s)"), nick, item.Message.Message)
  815. rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
  816. }
  817. case history.Kick:
  818. if eventPlayback {
  819. rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "HEVENT", "KICK", chname, item.Params[0], item.Message.Message)
  820. } else {
  821. message := fmt.Sprintf(client.t("%[1]s kicked %[2]s (%[3]s)"), nick, item.Params[0], item.Message.Message)
  822. rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
  823. }
  824. case history.Quit:
  825. if eventPlayback {
  826. rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "HEVENT", "QUIT", item.Message.Message)
  827. } else {
  828. if !playJoinsAsPrivmsg {
  829. continue // #474
  830. }
  831. message := fmt.Sprintf(client.t("%[1]s quit (%[2]s)"), nick, item.Message.Message)
  832. rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
  833. }
  834. case history.Nick:
  835. if eventPlayback {
  836. rb.AddFromClient(item.Message.Time, item.Message.Msgid, item.Nick, item.AccountName, nil, "HEVENT", "NICK", item.Params[0])
  837. } else {
  838. message := fmt.Sprintf(client.t("%[1]s changed nick to %[2]s"), nick, item.Params[0])
  839. rb.AddFromClient(item.Message.Time, utils.MungeSecretToken(item.Message.Msgid), histServMask, "*", nil, "PRIVMSG", chname, message)
  840. }
  841. }
  842. }
  843. }
  844. // SendTopic sends the channel topic to the given client.
  845. // `sendNoTopic` controls whether RPL_NOTOPIC is sent when the topic is unset
  846. func (channel *Channel) SendTopic(client *Client, rb *ResponseBuffer, sendNoTopic bool) {
  847. channel.stateMutex.RLock()
  848. name := channel.name
  849. topic := channel.topic
  850. topicSetBy := channel.topicSetBy
  851. topicSetTime := channel.topicSetTime
  852. _, hasClient := channel.members[client]
  853. channel.stateMutex.RUnlock()
  854. if !hasClient {
  855. rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, client.Nick(), channel.name, client.t("You're not on that channel"))
  856. return
  857. }
  858. if topic == "" {
  859. if sendNoTopic {
  860. rb.Add(nil, client.server.name, RPL_NOTOPIC, client.nick, name, client.t("No topic is set"))
  861. }
  862. return
  863. }
  864. rb.Add(nil, client.server.name, RPL_TOPIC, client.nick, name, topic)
  865. rb.Add(nil, client.server.name, RPL_TOPICTIME, client.nick, name, topicSetBy, strconv.FormatInt(topicSetTime.Unix(), 10))
  866. }
  867. // SetTopic sets the topic of this channel, if the client is allowed to do so.
  868. func (channel *Channel) SetTopic(client *Client, topic string, rb *ResponseBuffer) {
  869. if !(client.HasMode(modes.Operator) || channel.hasClient(client)) {
  870. rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, client.Nick(), channel.Name(), client.t("You're not on that channel"))
  871. return
  872. }
  873. if channel.flags.HasMode(modes.OpOnlyTopic) && !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
  874. rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, client.Nick(), channel.Name(), client.t("You're not a channel operator"))
  875. return
  876. }
  877. topicLimit := client.server.Config().Limits.TopicLen
  878. if len(topic) > topicLimit {
  879. topic = topic[:topicLimit]
  880. }
  881. channel.stateMutex.Lock()
  882. channel.topic = topic
  883. channel.topicSetBy = client.nickMaskString
  884. channel.topicSetTime = time.Now().UTC()
  885. channel.stateMutex.Unlock()
  886. prefix := client.NickMaskString()
  887. for _, member := range channel.Members() {
  888. for _, session := range member.Sessions() {
  889. if session == rb.session {
  890. rb.Add(nil, prefix, "TOPIC", channel.name, topic)
  891. } else {
  892. session.Send(nil, prefix, "TOPIC", channel.name, topic)
  893. }
  894. }
  895. }
  896. channel.MarkDirty(IncludeTopic)
  897. }
  898. // CanSpeak returns true if the client can speak on this channel.
  899. func (channel *Channel) CanSpeak(client *Client) bool {
  900. channel.stateMutex.RLock()
  901. defer channel.stateMutex.RUnlock()
  902. _, hasClient := channel.members[client]
  903. if channel.flags.HasMode(modes.NoOutside) && !hasClient {
  904. return false
  905. }
  906. if channel.flags.HasMode(modes.Moderated) && !channel.ClientIsAtLeast(client, modes.Voice) {
  907. return false
  908. }
  909. if channel.flags.HasMode(modes.RegisteredOnly) && client.Account() == "" {
  910. return false
  911. }
  912. return true
  913. }
  914. func msgCommandToHistType(command string) (history.ItemType, error) {
  915. switch command {
  916. case "PRIVMSG":
  917. return history.Privmsg, nil
  918. case "NOTICE":
  919. return history.Notice, nil
  920. case "TAGMSG":
  921. return history.Tagmsg, nil
  922. default:
  923. return history.ItemType(0), errInvalidParams
  924. }
  925. }
  926. func (channel *Channel) SendSplitMessage(command string, minPrefixMode modes.Mode, clientOnlyTags map[string]string, client *Client, message utils.SplitMessage, rb *ResponseBuffer) {
  927. histType, err := msgCommandToHistType(command)
  928. if err != nil {
  929. return
  930. }
  931. if !channel.CanSpeak(client) {
  932. if histType != history.Notice {
  933. rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, client.Nick(), channel.Name(), client.t("Cannot send to channel"))
  934. }
  935. return
  936. }
  937. nickmask := client.NickMaskString()
  938. account := client.AccountName()
  939. chname := channel.Name()
  940. // STATUSMSG targets are prefixed with the supplied min-prefix, e.g., @#channel
  941. if minPrefixMode != modes.Mode(0) {
  942. chname = fmt.Sprintf("%s%s", modes.ChannelModePrefixes[minPrefixMode], chname)
  943. }
  944. // send echo-message
  945. if rb.session.capabilities.Has(caps.EchoMessage) {
  946. var tagsToUse map[string]string
  947. if rb.session.capabilities.Has(caps.MessageTags) {
  948. tagsToUse = clientOnlyTags
  949. }
  950. if histType == history.Tagmsg && rb.session.capabilities.Has(caps.MessageTags) {
  951. rb.AddFromClient(message.Time, message.Msgid, nickmask, account, tagsToUse, command, chname)
  952. } else {
  953. rb.AddSplitMessageFromClient(nickmask, account, tagsToUse, command, chname, message)
  954. }
  955. }
  956. // send echo-message to other connected sessions
  957. for _, session := range client.Sessions() {
  958. if session == rb.session {
  959. continue
  960. }
  961. var tagsToUse map[string]string
  962. if session.capabilities.Has(caps.MessageTags) {
  963. tagsToUse = clientOnlyTags
  964. }
  965. if histType == history.Tagmsg && session.capabilities.Has(caps.MessageTags) {
  966. session.sendFromClientInternal(false, message.Time, message.Msgid, nickmask, account, tagsToUse, command, chname)
  967. } else if histType != history.Tagmsg {
  968. session.sendSplitMsgFromClientInternal(false, nickmask, account, tagsToUse, command, chname, message)
  969. }
  970. }
  971. for _, member := range channel.Members() {
  972. // echo-message is handled above, so skip sending the msg to the user themselves as well
  973. if member == client {
  974. continue
  975. }
  976. if minPrefixMode != modes.Mode(0) && !channel.ClientIsAtLeast(member, minPrefixMode) {
  977. // STATUSMSG
  978. continue
  979. }
  980. for _, session := range member.Sessions() {
  981. var tagsToUse map[string]string
  982. if session.capabilities.Has(caps.MessageTags) {
  983. tagsToUse = clientOnlyTags
  984. } else if histType == history.Tagmsg {
  985. continue
  986. }
  987. if histType == history.Tagmsg {
  988. session.sendFromClientInternal(false, message.Time, message.Msgid, nickmask, account, tagsToUse, command, chname)
  989. } else {
  990. session.sendSplitMsgFromClientInternal(false, nickmask, account, tagsToUse, command, chname, message)
  991. }
  992. }
  993. }
  994. channel.history.Add(history.Item{
  995. Type: histType,
  996. Message: message,
  997. Nick: nickmask,
  998. AccountName: account,
  999. Tags: clientOnlyTags,
  1000. })
  1001. }
  1002. func (channel *Channel) applyModeToMember(client *Client, mode modes.Mode, op modes.ModeOp, nick string, rb *ResponseBuffer) (result *modes.ModeChange) {
  1003. target := channel.server.clients.Get(nick)
  1004. if target == nil {
  1005. rb.Add(nil, client.server.name, ERR_NOSUCHNICK, client.Nick(), utils.SafeErrorParam(nick), client.t("No such nick"))
  1006. return nil
  1007. }
  1008. channel.stateMutex.Lock()
  1009. modeset, exists := channel.members[target]
  1010. if exists {
  1011. if modeset.SetMode(mode, op == modes.Add) {
  1012. result = &modes.ModeChange{
  1013. Op: op,
  1014. Mode: mode,
  1015. Arg: nick,
  1016. }
  1017. }
  1018. }
  1019. channel.stateMutex.Unlock()
  1020. if !exists {
  1021. rb.Add(nil, client.server.name, ERR_USERNOTINCHANNEL, client.Nick(), channel.Name(), client.t("They aren't on that channel"))
  1022. }
  1023. return
  1024. }
  1025. // ShowMaskList shows the given list to the client.
  1026. func (channel *Channel) ShowMaskList(client *Client, mode modes.Mode, rb *ResponseBuffer) {
  1027. // choose appropriate modes
  1028. var rpllist, rplendoflist string
  1029. if mode == modes.BanMask {
  1030. rpllist = RPL_BANLIST
  1031. rplendoflist = RPL_ENDOFBANLIST
  1032. } else if mode == modes.ExceptMask {
  1033. rpllist = RPL_EXCEPTLIST
  1034. rplendoflist = RPL_ENDOFEXCEPTLIST
  1035. } else if mode == modes.InviteMask {
  1036. rpllist = RPL_INVITELIST
  1037. rplendoflist = RPL_ENDOFINVITELIST
  1038. }
  1039. nick := client.Nick()
  1040. chname := channel.Name()
  1041. for mask, info := range channel.lists[mode].Masks() {
  1042. rb.Add(nil, client.server.name, rpllist, nick, chname, mask, info.CreatorNickmask, strconv.FormatInt(info.TimeCreated.Unix(), 10))
  1043. }
  1044. rb.Add(nil, client.server.name, rplendoflist, nick, chname, client.t("End of list"))
  1045. }
  1046. // Quit removes the given client from the channel
  1047. func (channel *Channel) Quit(client *Client) {
  1048. channelEmpty := func() bool {
  1049. channel.joinPartMutex.Lock()
  1050. defer channel.joinPartMutex.Unlock()
  1051. channel.stateMutex.Lock()
  1052. channel.members.Remove(client)
  1053. channelEmpty := len(channel.members) == 0
  1054. channel.stateMutex.Unlock()
  1055. channel.regenerateMembersCache()
  1056. return channelEmpty
  1057. }()
  1058. if channelEmpty {
  1059. client.server.channels.Cleanup(channel)
  1060. }
  1061. client.removeChannel(channel)
  1062. }
  1063. func (channel *Channel) Kick(client *Client, target *Client, comment string, rb *ResponseBuffer, hasPrivs bool) {
  1064. if !hasPrivs {
  1065. if !(client.HasMode(modes.Operator) || channel.hasClient(client)) {
  1066. rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, client.Nick(), channel.Name(), client.t("You're not on that channel"))
  1067. return
  1068. }
  1069. if !channel.ClientHasPrivsOver(client, target) {
  1070. rb.Add(nil, client.server.name, ERR_CHANOPRIVSNEEDED, client.Nick(), channel.Name(), client.t("You don't have enough channel privileges"))
  1071. return
  1072. }
  1073. }
  1074. if !channel.hasClient(target) {
  1075. rb.Add(nil, client.server.name, ERR_USERNOTINCHANNEL, client.Nick(), channel.Name(), client.t("They aren't on that channel"))
  1076. return
  1077. }
  1078. kicklimit := channel.server.Config().Limits.KickLen
  1079. if len(comment) > kicklimit {
  1080. comment = comment[:kicklimit]
  1081. }
  1082. message := utils.MakeSplitMessage(comment, true)
  1083. clientMask := client.NickMaskString()
  1084. clientAccount := client.AccountName()
  1085. targetNick := target.Nick()
  1086. chname := channel.Name()
  1087. for _, member := range channel.Members() {
  1088. for _, session := range member.Sessions() {
  1089. if session != rb.session {
  1090. session.sendFromClientInternal(false, message.Time, message.Msgid, clientMask, clientAccount, nil, "KICK", chname, targetNick, comment)
  1091. }
  1092. }
  1093. }
  1094. rb.Add(nil, clientMask, "KICK", chname, targetNick, comment)
  1095. histItem := history.Item{
  1096. Type: history.Kick,
  1097. Nick: clientMask,
  1098. AccountName: target.AccountName(),
  1099. Message: message,
  1100. }
  1101. histItem.Params[0] = targetNick
  1102. channel.history.Add(histItem)
  1103. channel.Quit(target)
  1104. }
  1105. // Invite invites the given client to the channel, if the inviter can do so.
  1106. func (channel *Channel) Invite(invitee *Client, inviter *Client, rb *ResponseBuffer) {
  1107. chname := channel.Name()
  1108. if channel.flags.HasMode(modes.InviteOnly) && !channel.ClientIsAtLeast(inviter, modes.ChannelOperator) {
  1109. rb.Add(nil, inviter.server.name, ERR_CHANOPRIVSNEEDED, inviter.Nick(), channel.Name(), inviter.t("You're not a channel operator"))
  1110. return
  1111. }
  1112. if !channel.hasClient(inviter) {
  1113. rb.Add(nil, inviter.server.name, ERR_NOTONCHANNEL, inviter.Nick(), channel.Name(), inviter.t("You're not on that channel"))
  1114. return
  1115. }
  1116. if channel.flags.HasMode(modes.InviteOnly) {
  1117. invitee.Invite(channel.NameCasefolded())
  1118. }
  1119. for _, member := range channel.Members() {
  1120. if member == inviter || member == invitee || !channel.ClientIsAtLeast(member, modes.Halfop) {
  1121. continue
  1122. }
  1123. for _, session := range member.Sessions() {
  1124. if session.capabilities.Has(caps.InviteNotify) {
  1125. session.Send(nil, inviter.NickMaskString(), "INVITE", invitee.Nick(), chname)
  1126. }
  1127. }
  1128. }
  1129. cnick := inviter.Nick()
  1130. tnick := invitee.Nick()
  1131. rb.Add(nil, inviter.server.name, RPL_INVITING, cnick, tnick, chname)
  1132. invitee.Send(nil, inviter.NickMaskString(), "INVITE", tnick, chname)
  1133. if invitee.Away() {
  1134. rb.Add(nil, inviter.server.name, RPL_AWAY, cnick, tnick, invitee.AwayMessage())
  1135. }
  1136. }