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.

text.go 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
  2. // released under the MIT license
  3. package utils
  4. import (
  5. "bytes"
  6. "strings"
  7. "time"
  8. )
  9. func IsRestrictedCTCPMessage(message string) bool {
  10. // block all CTCP privmsgs to Tor clients except for ACTION
  11. // DCC can potentially be used for deanonymization, the others for fingerprinting
  12. return strings.HasPrefix(message, "\x01") && !strings.HasPrefix(message, "\x01ACTION")
  13. }
  14. type MessagePair struct {
  15. Message string
  16. Concat bool // should be relayed with the multiline-concat tag
  17. }
  18. // SplitMessage represents a message that's been split for sending.
  19. // Two possibilities:
  20. // (a) Standard message that can be relayed on a single 512-byte line
  21. // (MessagePair contains the message, Wrapped == nil)
  22. // (b) multiline message that was split on the client side
  23. // (Message == "", Wrapped contains the split lines)
  24. type SplitMessage struct {
  25. Message string
  26. Msgid string
  27. Split []MessagePair
  28. Time time.Time
  29. }
  30. func MakeMessage(original string) (result SplitMessage) {
  31. result.Message = original
  32. result.Msgid = GenerateSecretToken()
  33. result.Time = time.Now().UTC()
  34. return
  35. }
  36. func (sm *SplitMessage) Append(message string, concat bool) {
  37. if sm.Msgid == "" {
  38. sm.Msgid = GenerateSecretToken()
  39. }
  40. sm.Split = append(sm.Split, MessagePair{
  41. Message: message,
  42. Concat: concat,
  43. })
  44. }
  45. func (sm *SplitMessage) SetTime() {
  46. sm.Time = time.Now().UTC()
  47. }
  48. func (sm *SplitMessage) LenLines() int {
  49. if sm.Split == nil {
  50. if sm.Message == "" {
  51. return 0
  52. } else {
  53. return 1
  54. }
  55. }
  56. return len(sm.Split)
  57. }
  58. func (sm *SplitMessage) LenBytes() (result int) {
  59. if sm.Split == nil {
  60. return len(sm.Message)
  61. }
  62. for i := 0; i < len(sm.Split); i++ {
  63. result += len(sm.Split[i].Message)
  64. }
  65. return
  66. }
  67. func (sm *SplitMessage) IsRestrictedCTCPMessage() bool {
  68. if IsRestrictedCTCPMessage(sm.Message) {
  69. return true
  70. }
  71. for i := 0; i < len(sm.Split); i++ {
  72. if IsRestrictedCTCPMessage(sm.Split[i].Message) {
  73. return true
  74. }
  75. }
  76. return false
  77. }
  78. func (sm *SplitMessage) IsMultiline() bool {
  79. return sm.Message == "" && len(sm.Split) != 0
  80. }
  81. func (sm *SplitMessage) Is512() bool {
  82. return sm.Message != ""
  83. }
  84. // TokenLineBuilder is a helper for building IRC lines composed of delimited tokens,
  85. // with a maximum line length.
  86. type TokenLineBuilder struct {
  87. lineLen int
  88. delim string
  89. buf bytes.Buffer
  90. result []string
  91. }
  92. func (t *TokenLineBuilder) Initialize(lineLen int, delim string) {
  93. t.lineLen = lineLen
  94. t.delim = delim
  95. }
  96. // Add adds a token to the line, creating a new line if necessary.
  97. func (t *TokenLineBuilder) Add(token string) {
  98. tokenLen := len(token)
  99. if t.buf.Len() != 0 {
  100. tokenLen += len(t.delim)
  101. }
  102. if t.lineLen < t.buf.Len()+tokenLen {
  103. t.result = append(t.result, t.buf.String())
  104. t.buf.Reset()
  105. }
  106. if t.buf.Len() != 0 {
  107. t.buf.WriteString(t.delim)
  108. }
  109. t.buf.WriteString(token)
  110. }
  111. // Lines terminates the line-building and returns all the lines.
  112. func (t *TokenLineBuilder) Lines() (result []string) {
  113. result = t.result
  114. t.result = nil
  115. if t.buf.Len() != 0 {
  116. result = append(result, t.buf.String())
  117. t.buf.Reset()
  118. }
  119. return
  120. }