encoder.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. package binary
  2. import (
  3. "fmt"
  4. "github.com/Rhymen/go-whatsapp/binary/token"
  5. "math"
  6. "strconv"
  7. "strings"
  8. )
  9. type binaryEncoder struct {
  10. data []byte
  11. }
  12. func NewEncoder() *binaryEncoder {
  13. return &binaryEncoder{make([]byte, 0)}
  14. }
  15. func (w *binaryEncoder) GetData() []byte {
  16. return w.data
  17. }
  18. func (w *binaryEncoder) pushByte(b byte) {
  19. w.data = append(w.data, b)
  20. }
  21. func (w *binaryEncoder) pushBytes(bytes []byte) {
  22. w.data = append(w.data, bytes...)
  23. }
  24. func (w *binaryEncoder) pushIntN(value, n int, littleEndian bool) {
  25. for i := 0; i < n; i++ {
  26. var curShift int
  27. if littleEndian {
  28. curShift = i
  29. } else {
  30. curShift = n - i - 1
  31. }
  32. w.pushByte(byte((value >> uint(curShift*8)) & 0xFF))
  33. }
  34. }
  35. func (w *binaryEncoder) pushInt20(value int) {
  36. w.pushBytes([]byte{byte((value >> 16) & 0x0F), byte((value >> 8) & 0xFF), byte(value & 0xFF)})
  37. }
  38. func (w *binaryEncoder) pushInt8(value int) {
  39. w.pushIntN(value, 1, false)
  40. }
  41. func (w *binaryEncoder) pushInt16(value int) {
  42. w.pushIntN(value, 2, false)
  43. }
  44. func (w *binaryEncoder) pushInt32(value int) {
  45. w.pushIntN(value, 4, false)
  46. }
  47. func (w *binaryEncoder) pushInt64(value int) {
  48. w.pushIntN(value, 8, false)
  49. }
  50. func (w *binaryEncoder) pushString(value string) {
  51. w.pushBytes([]byte(value))
  52. }
  53. func (w *binaryEncoder) writeByteLength(length int) error {
  54. if length > math.MaxInt32 {
  55. return fmt.Errorf("length is too large: %d", length)
  56. } else if length >= (1 << 20) {
  57. w.pushByte(token.BINARY_32)
  58. w.pushInt32(length)
  59. } else if length >= 256 {
  60. w.pushByte(token.BINARY_20)
  61. w.pushInt20(length)
  62. } else {
  63. w.pushByte(token.BINARY_8)
  64. w.pushInt8(length)
  65. }
  66. return nil
  67. }
  68. func (w *binaryEncoder) WriteNode(n Node) error {
  69. numAttributes := 0
  70. if n.Attributes != nil {
  71. numAttributes = len(n.Attributes)
  72. }
  73. hasContent := 0
  74. if n.Content != nil {
  75. hasContent = 1
  76. }
  77. w.writeListStart(2*numAttributes + 1 + hasContent)
  78. if err := w.writeString(n.Description, false); err != nil {
  79. return err
  80. }
  81. if err := w.writeAttributes(n.Attributes); err != nil {
  82. return err
  83. }
  84. if err := w.writeChildren(n.Content); err != nil {
  85. return err
  86. }
  87. return nil
  88. }
  89. func (w *binaryEncoder) writeString(tok string, i bool) error {
  90. if !i && tok == "c.us" {
  91. if err := w.writeToken(token.IndexOfSingleToken("s.whatsapp.net")); err != nil {
  92. return err
  93. }
  94. return nil
  95. }
  96. tokenIndex := token.IndexOfSingleToken(tok)
  97. if tokenIndex == -1 {
  98. jidSepIndex := strings.Index(tok, "@")
  99. if jidSepIndex < 1 {
  100. w.writeStringRaw(tok)
  101. } else {
  102. w.writeJid(tok[:jidSepIndex], tok[jidSepIndex+1:])
  103. }
  104. } else {
  105. if tokenIndex < token.SINGLE_BYTE_MAX {
  106. if err := w.writeToken(tokenIndex); err != nil {
  107. return err
  108. }
  109. } else {
  110. singleByteOverflow := tokenIndex - token.SINGLE_BYTE_MAX
  111. dictionaryIndex := singleByteOverflow >> 8
  112. if dictionaryIndex < 0 || dictionaryIndex > 3 {
  113. return fmt.Errorf("double byte dictionary token out of range: %v", tok)
  114. }
  115. if err := w.writeToken(token.DICTIONARY_0 + dictionaryIndex); err != nil {
  116. return err
  117. }
  118. if err := w.writeToken(singleByteOverflow % 256); err != nil {
  119. return err
  120. }
  121. }
  122. }
  123. return nil
  124. }
  125. func (w *binaryEncoder) writeStringRaw(value string) error {
  126. if err := w.writeByteLength(len(value)); err != nil {
  127. return err
  128. }
  129. w.pushString(value)
  130. return nil
  131. }
  132. func (w *binaryEncoder) writeJid(jidLeft, jidRight string) error {
  133. w.pushByte(token.JID_PAIR)
  134. if jidLeft != "" {
  135. if err := w.writePackedBytes(jidLeft); err != nil {
  136. return err
  137. }
  138. } else {
  139. if err := w.writeToken(token.LIST_EMPTY); err != nil {
  140. return err
  141. }
  142. }
  143. if err := w.writeString(jidRight, false); err != nil {
  144. return err
  145. }
  146. return nil
  147. }
  148. func (w *binaryEncoder) writeToken(tok int) error {
  149. if tok < len(token.SingleByteTokens) {
  150. w.pushByte(byte(tok))
  151. } else if tok <= 500 {
  152. return fmt.Errorf("invalid token: %d", tok)
  153. }
  154. return nil
  155. }
  156. func (w *binaryEncoder) writeAttributes(attributes map[string]string) error {
  157. if attributes == nil {
  158. return nil
  159. }
  160. for key, val := range attributes {
  161. if val == "" {
  162. continue
  163. }
  164. if err := w.writeString(key, false); err != nil {
  165. return err
  166. }
  167. if err := w.writeString(val, false); err != nil {
  168. return err
  169. }
  170. }
  171. return nil
  172. }
  173. func (w *binaryEncoder) writeChildren(children interface{}) error {
  174. if children == nil {
  175. return nil
  176. }
  177. switch childs := children.(type) {
  178. case string:
  179. if err := w.writeString(childs, true); err != nil {
  180. return err
  181. }
  182. case []byte:
  183. if err := w.writeByteLength(len(childs)); err != nil {
  184. return err
  185. }
  186. w.pushBytes(childs)
  187. case []Node:
  188. w.writeListStart(len(childs))
  189. for _, n := range childs {
  190. if err := w.WriteNode(n); err != nil {
  191. return err
  192. }
  193. }
  194. default:
  195. return fmt.Errorf("cannot write child of type: %T", children)
  196. }
  197. return nil
  198. }
  199. func (w *binaryEncoder) writeListStart(listSize int) {
  200. if listSize == 0 {
  201. w.pushByte(byte(token.LIST_EMPTY))
  202. } else if listSize < 256 {
  203. w.pushByte(byte(token.LIST_8))
  204. w.pushInt8(listSize)
  205. } else {
  206. w.pushByte(byte(token.LIST_16))
  207. w.pushInt16(listSize)
  208. }
  209. }
  210. func (w *binaryEncoder) writePackedBytes(value string) error {
  211. if err := w.writePackedBytesImpl(value, token.NIBBLE_8); err != nil {
  212. if err := w.writePackedBytesImpl(value, token.HEX_8); err != nil {
  213. return err
  214. }
  215. }
  216. return nil
  217. }
  218. func (w *binaryEncoder) writePackedBytesImpl(value string, dataType int) error {
  219. numBytes := len(value)
  220. if numBytes > token.PACKED_MAX {
  221. return fmt.Errorf("too many bytes to pack: %d", numBytes)
  222. }
  223. w.pushByte(byte(dataType))
  224. x := 0
  225. if numBytes%2 != 0 {
  226. x = 128
  227. }
  228. w.pushByte(byte(x | int(math.Ceil(float64(numBytes)/2.0))))
  229. for i, l := 0, numBytes/2; i < l; i++ {
  230. b, err := w.packBytePair(dataType, value[2*i:2*i+1], value[2*i+1:2*i+2])
  231. if err != nil {
  232. return err
  233. }
  234. w.pushByte(byte(b))
  235. }
  236. if (numBytes % 2) != 0 {
  237. b, err := w.packBytePair(dataType, value[numBytes-1:], "\x00")
  238. if err != nil {
  239. return err
  240. }
  241. w.pushByte(byte(b))
  242. }
  243. return nil
  244. }
  245. func (w *binaryEncoder) packBytePair(packType int, part1, part2 string) (int, error) {
  246. if packType == token.NIBBLE_8 {
  247. n1, err := packNibble(part1)
  248. if err != nil {
  249. return 0, err
  250. }
  251. n2, err := packNibble(part2)
  252. if err != nil {
  253. return 0, err
  254. }
  255. return (n1 << 4) | n2, nil
  256. } else if packType == token.HEX_8 {
  257. n1, err := packHex(part1)
  258. if err != nil {
  259. return 0, err
  260. }
  261. n2, err := packHex(part2)
  262. if err != nil {
  263. return 0, err
  264. }
  265. return (n1 << 4) | n2, nil
  266. } else {
  267. return 0, fmt.Errorf("invalid pack type (%d) for byte pair: %s / %s", packType, part1, part2)
  268. }
  269. }
  270. func packNibble(value string) (int, error) {
  271. if value >= "0" && value <= "9" {
  272. return strconv.Atoi(value)
  273. } else if value == "-" {
  274. return 10, nil
  275. } else if value == "." {
  276. return 11, nil
  277. } else if value == "\x00" {
  278. return 15, nil
  279. }
  280. return 0, fmt.Errorf("invalid string to pack as nibble: %v", value)
  281. }
  282. func packHex(value string) (int, error) {
  283. if (value >= "0" && value <= "9") || (value >= "A" && value <= "F") || (value >= "a" && value <= "f") {
  284. d, err := strconv.ParseInt(value, 16, 0)
  285. return int(d), err
  286. } else if value == "\x00" {
  287. return 15, nil
  288. }
  289. return 0, fmt.Errorf("invalid string to pack as hex: %v", value)
  290. }