locate.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package server
  2. import (
  3. "errors"
  4. "io"
  5. "github.com/mkaminski/goaim/oscar"
  6. )
  7. type LocateHandler interface {
  8. RightsQueryHandler() XMessage
  9. SetDirInfoHandler() XMessage
  10. SetInfoHandler(sess *Session, sm SessionManager, fm FeedbagManager, pm ProfileManager, snacPayloadIn oscar.SNAC_0x02_0x04_LocateSetInfo) error
  11. SetKeywordInfoHandler() XMessage
  12. UserInfoQuery2Handler(sess *Session, sm SessionManager, fm FeedbagManager, pm ProfileManager, snacPayloadIn oscar.SNAC_0x02_0x15_LocateUserInfoQuery2) (XMessage, error)
  13. }
  14. func NewLocateRouter() LocateRouter {
  15. return LocateRouter{
  16. LocateHandler: LocateService{},
  17. }
  18. }
  19. type LocateRouter struct {
  20. LocateHandler
  21. }
  22. func (rt LocateRouter) RouteLocate(sess *Session, sm SessionManager, fm *FeedbagStore, snac oscar.SnacFrame, r io.Reader, w io.Writer, sequence *uint32) error {
  23. switch snac.SubGroup {
  24. case oscar.LocateRightsQuery:
  25. outSNAC := rt.RightsQueryHandler()
  26. return writeOutSNAC(snac, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  27. case oscar.LocateSetInfo:
  28. snacPayloadIn := oscar.SNAC_0x02_0x04_LocateSetInfo{}
  29. if err := oscar.Unmarshal(&snacPayloadIn, r); err != nil {
  30. return err
  31. }
  32. return rt.SetInfoHandler(sess, sm, fm, fm, snacPayloadIn)
  33. case oscar.LocateSetDirInfo:
  34. snacPayloadIn := oscar.SNAC_0x02_0x09_LocateSetDirInfo{}
  35. if err := oscar.Unmarshal(&snacPayloadIn, r); err != nil {
  36. return err
  37. }
  38. outSNAC := rt.SetDirInfoHandler()
  39. return writeOutSNAC(snac, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  40. case oscar.LocateGetDirInfo:
  41. snacPayloadIn := oscar.SNAC_0x02_0x0B_LocateGetDirInfo{}
  42. return oscar.Unmarshal(&snacPayloadIn, r)
  43. case oscar.LocateSetKeywordInfo:
  44. snacPayloadIn := oscar.SNAC_0x02_0x0F_LocateSetKeywordInfo{}
  45. if err := oscar.Unmarshal(&snacPayloadIn, r); err != nil {
  46. return err
  47. }
  48. outSNAC := rt.SetKeywordInfoHandler()
  49. return writeOutSNAC(snac, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  50. case oscar.LocateUserInfoQuery2:
  51. snacPayloadIn := oscar.SNAC_0x02_0x15_LocateUserInfoQuery2{}
  52. if err := oscar.Unmarshal(&snacPayloadIn, r); err != nil {
  53. return err
  54. }
  55. outSNAC, err := rt.UserInfoQuery2Handler(sess, sm, fm, fm, snacPayloadIn)
  56. if err != nil {
  57. return err
  58. }
  59. return writeOutSNAC(snac, outSNAC.snacFrame, outSNAC.snacOut, sequence, w)
  60. default:
  61. return ErrUnsupportedSubGroup
  62. }
  63. }
  64. type LocateService struct {
  65. }
  66. func (s LocateService) RightsQueryHandler() XMessage {
  67. return XMessage{
  68. snacFrame: oscar.SnacFrame{
  69. FoodGroup: oscar.LOCATE,
  70. SubGroup: oscar.LocateRightsReply,
  71. },
  72. snacOut: oscar.SNAC_0x02_0x03_LocateRightsReply{
  73. TLVRestBlock: oscar.TLVRestBlock{
  74. TLVList: oscar.TLVList{
  75. {
  76. TType: 0x01,
  77. Val: uint16(1000),
  78. },
  79. {
  80. TType: 0x02,
  81. Val: uint16(1000),
  82. },
  83. {
  84. TType: 0x03,
  85. Val: uint16(1000),
  86. },
  87. {
  88. TType: 0x04,
  89. Val: uint16(1000),
  90. },
  91. {
  92. TType: 0x05,
  93. Val: uint16(1000),
  94. },
  95. },
  96. },
  97. },
  98. }
  99. }
  100. func (s LocateService) SetInfoHandler(sess *Session, sm SessionManager, fm FeedbagManager, pm ProfileManager, snacPayloadIn oscar.SNAC_0x02_0x04_LocateSetInfo) error {
  101. // update profile
  102. if profile, hasProfile := snacPayloadIn.GetString(oscar.LocateTLVTagsInfoSigData); hasProfile {
  103. if err := pm.UpsertProfile(sess.ScreenName, profile); err != nil {
  104. return err
  105. }
  106. }
  107. // broadcast away message change to buddies
  108. if awayMsg, hasAwayMsg := snacPayloadIn.GetString(oscar.LocateTLVTagsInfoUnavailableData); hasAwayMsg {
  109. sess.SetAwayMessage(awayMsg)
  110. if err := BroadcastArrival(sess, sm, fm); err != nil {
  111. return err
  112. }
  113. }
  114. return nil
  115. }
  116. func (s LocateService) UserInfoQuery2Handler(sess *Session, sm SessionManager, fm FeedbagManager, pm ProfileManager, snacPayloadIn oscar.SNAC_0x02_0x15_LocateUserInfoQuery2) (XMessage, error) {
  117. blocked, err := fm.Blocked(sess.ScreenName, snacPayloadIn.ScreenName)
  118. switch {
  119. case err != nil:
  120. return XMessage{}, err
  121. case blocked != BlockedNo:
  122. return XMessage{
  123. snacFrame: oscar.SnacFrame{
  124. FoodGroup: oscar.LOCATE,
  125. SubGroup: oscar.LocateErr,
  126. },
  127. snacOut: oscar.SnacError{
  128. Code: ErrorCodeNotLoggedOn,
  129. },
  130. }, nil
  131. }
  132. buddySess, err := sm.RetrieveByScreenName(snacPayloadIn.ScreenName)
  133. switch {
  134. case errors.Is(err, ErrSessNotFound):
  135. return XMessage{
  136. snacFrame: oscar.SnacFrame{
  137. FoodGroup: oscar.LOCATE,
  138. SubGroup: oscar.LocateErr,
  139. },
  140. snacOut: oscar.SnacError{
  141. Code: ErrorCodeNotLoggedOn,
  142. },
  143. }, nil
  144. case err != nil:
  145. return XMessage{}, err
  146. }
  147. var list oscar.TLVList
  148. if snacPayloadIn.RequestProfile() {
  149. profile, err := pm.RetrieveProfile(snacPayloadIn.ScreenName)
  150. if err != nil {
  151. return XMessage{}, err
  152. }
  153. list.AddTLVList([]oscar.TLV{
  154. {
  155. TType: oscar.LocateTLVTagsInfoSigMime,
  156. Val: `text/aolrtf; charset="us-ascii"`,
  157. },
  158. {
  159. TType: oscar.LocateTLVTagsInfoSigData,
  160. Val: profile,
  161. },
  162. })
  163. }
  164. if snacPayloadIn.RequestAwayMessage() {
  165. list.AddTLVList([]oscar.TLV{
  166. {
  167. TType: oscar.LocateTLVTagsInfoUnavailableMime,
  168. Val: `text/aolrtf; charset="us-ascii"`,
  169. },
  170. {
  171. TType: oscar.LocateTLVTagsInfoUnavailableData,
  172. Val: buddySess.GetAwayMessage(),
  173. },
  174. })
  175. }
  176. return XMessage{
  177. snacFrame: oscar.SnacFrame{
  178. FoodGroup: oscar.LOCATE,
  179. SubGroup: oscar.LocateUserInfoReply,
  180. },
  181. snacOut: oscar.SNAC_0x02_0x06_LocateUserInfoReply{
  182. TLVUserInfo: buddySess.GetTLVUserInfo(),
  183. LocateInfo: oscar.TLVRestBlock{
  184. TLVList: list,
  185. },
  186. },
  187. }, nil
  188. }
  189. func (s LocateService) SetDirInfoHandler() XMessage {
  190. return XMessage{
  191. snacFrame: oscar.SnacFrame{
  192. FoodGroup: oscar.LOCATE,
  193. SubGroup: oscar.LocateSetDirReply,
  194. },
  195. snacOut: oscar.SNAC_0x02_0x0A_LocateSetDirReply{
  196. Result: 1,
  197. },
  198. }
  199. }
  200. func (s LocateService) SetKeywordInfoHandler() XMessage {
  201. return XMessage{
  202. snacFrame: oscar.SnacFrame{
  203. FoodGroup: oscar.LOCATE,
  204. SubGroup: oscar.LocateSetKeywordReply,
  205. },
  206. snacOut: oscar.SNAC_0x02_0x10_LocateSetKeywordReply{
  207. Unknown: 1,
  208. },
  209. }
  210. }