diff --git a/foodgroup/admin.go b/foodgroup/admin.go index 8c57b194..74a4799d 100644 --- a/foodgroup/admin.go +++ b/foodgroup/admin.go @@ -95,29 +95,29 @@ func (s AdminService) InfoQuery(_ context.Context, sess *state.Session, frame wi tlvList := wire.TLVList{} - if _, hasRegStatus := body.TLVRestBlock.Slice(wire.AdminTLVRegistrationStatus); hasRegStatus { + if _, hasRegStatus := body.TLVRestBlock.Bytes(wire.AdminTLVRegistrationStatus); hasRegStatus { regStatus, err := s.accountManager.RegStatusByName(sess.IdentScreenName()) if err != nil { return wire.SNACMessage{}, err } - tlvList.Append(wire.NewTLV(wire.AdminTLVRegistrationStatus, regStatus)) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVRegistrationStatus, regStatus)) return getAdminInfoReply(tlvList), nil } - if _, hasEmail := body.TLVRestBlock.Slice(wire.AdminTLVEmailAddress); hasEmail { + if _, hasEmail := body.TLVRestBlock.Bytes(wire.AdminTLVEmailAddress); hasEmail { e, err := s.accountManager.EmailAddressByName(sess.IdentScreenName()) if errors.Is(err, state.ErrNoEmailAddress) { - tlvList.Append(wire.NewTLV(wire.AdminTLVEmailAddress, "")) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVEmailAddress, "")) } else if err != nil { return wire.SNACMessage{}, err } else { - tlvList.Append(wire.NewTLV(wire.AdminTLVEmailAddress, e.Address)) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVEmailAddress, e.Address)) } return getAdminInfoReply(tlvList), nil } - if _, hasNickName := body.TLVRestBlock.Slice(wire.AdminTLVScreenNameFormatted); hasNickName { - tlvList.Append(wire.NewTLV(wire.AdminTLVScreenNameFormatted, sess.DisplayScreenName().String())) + if _, hasNickName := body.TLVRestBlock.Bytes(wire.AdminTLVScreenNameFormatted); hasNickName { + tlvList.Append(wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, sess.DisplayScreenName().String())) return getAdminInfoReply(tlvList), nil } @@ -196,11 +196,11 @@ func (s AdminService) InfoChangeRequest(ctx context.Context, sess *state.Session tlvList := wire.TLVList{} - if sn, hasScreenNameFormatted := body.TLVRestBlock.Slice(wire.AdminTLVScreenNameFormatted); hasScreenNameFormatted { + if sn, hasScreenNameFormatted := body.TLVRestBlock.Bytes(wire.AdminTLVScreenNameFormatted); hasScreenNameFormatted { proposedName := state.DisplayScreenName(sn) if ok, errorCode := validateProposedName(proposedName); !ok { - tlvList.Append(wire.NewTLV(wire.AdminTLVErrorCode, errorCode)) - tlvList.Append(wire.NewTLV(wire.AdminTLVUrl, "")) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVErrorCode, errorCode)) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVUrl, "")) return getAdminChangeReply(tlvList), nil } if err := s.accountManager.UpdateDisplayScreenName(proposedName); err != nil { @@ -219,26 +219,26 @@ func (s AdminService) InfoChangeRequest(ctx context.Context, sess *state.Session TLVUserInfo: sess.TLVUserInfo(), }, }) - tlvList.Append(wire.NewTLV(wire.AdminTLVScreenNameFormatted, proposedName.String())) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, proposedName.String())) return getAdminChangeReply(tlvList), nil } - if emailAddress, hasEmailAddress := body.TLVRestBlock.Slice(wire.AdminTLVEmailAddress); hasEmailAddress { + if emailAddress, hasEmailAddress := body.TLVRestBlock.Bytes(wire.AdminTLVEmailAddress); hasEmailAddress { e, errorCode := validateProposedEmailAddress(emailAddress) if errorCode != 0 { - tlvList.Append(wire.NewTLV(wire.AdminTLVErrorCode, errorCode)) - tlvList.Append(wire.NewTLV(wire.AdminTLVUrl, "")) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVErrorCode, errorCode)) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVUrl, "")) return getAdminChangeReply(tlvList), nil } if err := s.accountManager.UpdateEmailAddress(e, sess.IdentScreenName()); err != nil { return wire.SNACMessage{}, err } - tlvList.Append(wire.NewTLV(wire.AdminTLVEmailAddress, e.Address)) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVEmailAddress, e.Address)) return getAdminChangeReply(tlvList), nil } - if regStatus, hasRegStatus := body.TLVRestBlock.Uint16(wire.AdminTLVRegistrationStatus); hasRegStatus { + if regStatus, hasRegStatus := body.TLVRestBlock.Uint16BE(wire.AdminTLVRegistrationStatus); hasRegStatus { switch regStatus { case wire.AdminInfoRegStatusFullDisclosure, @@ -247,11 +247,11 @@ func (s AdminService) InfoChangeRequest(ctx context.Context, sess *state.Session if err := s.accountManager.UpdateRegStatus(regStatus, sess.IdentScreenName()); err != nil { return wire.SNACMessage{}, err } - tlvList.Append(wire.NewTLV(wire.AdminTLVRegistrationStatus, regStatus)) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVRegistrationStatus, regStatus)) return getAdminChangeReply(tlvList), nil } - tlvList.Append(wire.NewTLV(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidRegistrationPreference)) - tlvList.Append(wire.NewTLV(wire.AdminTLVUrl, "")) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidRegistrationPreference)) + tlvList.Append(wire.NewTLVBE(wire.AdminTLVUrl, "")) return getAdminChangeReply(tlvList), nil } diff --git a/foodgroup/admin_test.go b/foodgroup/admin_test.go index a1a1bf2b..d0bed7da 100644 --- a/foodgroup/admin_test.go +++ b/foodgroup/admin_test.go @@ -4,11 +4,12 @@ import ( "net/mail" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/mk6i/retro-aim-server/config" "github.com/mk6i/retro-aim-server/state" "github.com/mk6i/retro-aim-server/wire" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" ) func TestAdminService_ConfirmRequest(t *testing.T) { @@ -236,7 +237,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Body: wire.SNAC_0x07_0x02_AdminInfoQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVRegistrationStatus, uint16(0x00))}, + wire.NewTLVBE(wire.AdminTLVRegistrationStatus, uint16(0x00))}, }, }, }, @@ -250,7 +251,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusLimitDisclosure), + wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusLimitDisclosure), }, }, }, @@ -279,7 +280,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Body: wire.SNAC_0x07_0x02_AdminInfoQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVEmailAddress, uint16(0x00))}, + wire.NewTLVBE(wire.AdminTLVEmailAddress, uint16(0x00))}, }, }, }, @@ -293,7 +294,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"), + wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"), }, }, }, @@ -324,7 +325,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Body: wire.SNAC_0x07_0x02_AdminInfoQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVEmailAddress, uint16(0x00))}, + wire.NewTLVBE(wire.AdminTLVEmailAddress, uint16(0x00))}, }, }, }, @@ -338,7 +339,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVEmailAddress, ""), + wire.NewTLVBE(wire.AdminTLVEmailAddress, ""), }, }, }, @@ -367,7 +368,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Body: wire.SNAC_0x07_0x02_AdminInfoQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, uint16(0x00))}, + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, uint16(0x00))}, }, }, }, @@ -381,7 +382,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, "ChattingChuck"), + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "ChattingChuck"), }, }, }, @@ -399,7 +400,7 @@ func TestAdminService_InfoQuery(t *testing.T) { Body: wire.SNAC_0x07_0x02_AdminInfoQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(uint16(0x99), uint16(0x00))}, + wire.NewTLVBE(uint16(0x99), uint16(0x00))}, }, }, }, @@ -511,7 +512,7 @@ func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"), + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"), }, }, }, @@ -526,7 +527,7 @@ func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"), + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"), }, }, }, @@ -544,7 +545,7 @@ func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, "c h a t t i n g c h u c k")}, + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "c h a t t i n g c h u c k")}, }, }, }, @@ -558,8 +559,8 @@ func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidNickNameLength), - wire.NewTLV(wire.AdminTLVUrl, ""), + wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidNickNameLength), + wire.NewTLVBE(wire.AdminTLVUrl, ""), }, }, }, @@ -577,7 +578,7 @@ func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, "QuietQuinton")}, + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "QuietQuinton")}, }, }, }, @@ -591,8 +592,8 @@ func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVErrorCode, wire.AdminInfoErrorValidateNickName), - wire.NewTLV(wire.AdminTLVUrl, ""), + wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorValidateNickName), + wire.NewTLVBE(wire.AdminTLVUrl, ""), }, }, }, @@ -610,7 +611,7 @@ func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, "ChattingChuck ")}, + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "ChattingChuck ")}, }, }, }, @@ -624,8 +625,8 @@ func TestAdminService_InfoChangeRequest_ScreenName(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidNickName), - wire.NewTLV(wire.AdminTLVUrl, ""), + wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidNickName), + wire.NewTLVBE(wire.AdminTLVUrl, ""), }, }, }, @@ -725,7 +726,7 @@ func TestAdminService_InfoChangeRequest_EmailAddress(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"), + wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"), }, }, }, @@ -740,7 +741,7 @@ func TestAdminService_InfoChangeRequest_EmailAddress(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"), + wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@aol.com"), }, }, }, @@ -758,7 +759,7 @@ func TestAdminService_InfoChangeRequest_EmailAddress(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVEmailAddress, "chattingchuck@@@@@@@aol.com"), + wire.NewTLVBE(wire.AdminTLVEmailAddress, "chattingchuck@@@@@@@aol.com"), }, }, }, @@ -773,8 +774,8 @@ func TestAdminService_InfoChangeRequest_EmailAddress(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidEmail), - wire.NewTLV(wire.AdminTLVUrl, ""), + wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidEmail), + wire.NewTLVBE(wire.AdminTLVUrl, ""), }, }, }, @@ -792,7 +793,7 @@ func TestAdminService_InfoChangeRequest_EmailAddress(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVEmailAddress, longEmailAddress), + wire.NewTLVBE(wire.AdminTLVEmailAddress, longEmailAddress), }, }, }, @@ -807,8 +808,8 @@ func TestAdminService_InfoChangeRequest_EmailAddress(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidEmailLength), - wire.NewTLV(wire.AdminTLVUrl, ""), + wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidEmailLength), + wire.NewTLVBE(wire.AdminTLVUrl, ""), }, }, }, @@ -885,7 +886,7 @@ func TestAdminService_InfoChangeRequest_RegStatus(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusNoDisclosure), + wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusNoDisclosure), }, }, }, @@ -900,7 +901,7 @@ func TestAdminService_InfoChangeRequest_RegStatus(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusNoDisclosure), + wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusNoDisclosure), }, }, }, @@ -918,7 +919,7 @@ func TestAdminService_InfoChangeRequest_RegStatus(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVRegistrationStatus, uint16(0x1337)), + wire.NewTLVBE(wire.AdminTLVRegistrationStatus, uint16(0x1337)), }, }, }, @@ -933,8 +934,8 @@ func TestAdminService_InfoChangeRequest_RegStatus(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidRegistrationPreference), - wire.NewTLV(wire.AdminTLVUrl, ""), + wire.NewTLVBE(wire.AdminTLVErrorCode, wire.AdminInfoErrorInvalidRegistrationPreference), + wire.NewTLVBE(wire.AdminTLVUrl, ""), }, }, }, diff --git a/foodgroup/auth.go b/foodgroup/auth.go index de0dafc8..f4108d38 100644 --- a/foodgroup/auth.go +++ b/foodgroup/auth.go @@ -201,7 +201,7 @@ func (s AuthService) BUCPChallenge( Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidUsernameOrPassword), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidUsernameOrPassword), }, }, }, @@ -318,9 +318,9 @@ func (s AuthService) login( // get the password from the appropriate TLV. older clients have a // roasted password, newer clients have a hashed password. ICQ may omit // the password TLV when logging in without saved password. - if md5Hash, hasMD5 := TLVList.Slice(wire.LoginTLVTagsPasswordHash); hasMD5 { + if md5Hash, hasMD5 := TLVList.Bytes(wire.LoginTLVTagsPasswordHash); hasMD5 { loginOK = user.ValidateHash(md5Hash) - } else if roastedPass, hasRoasted := TLVList.Slice(wire.LoginTLVTagsRoastedPassword); hasRoasted { + } else if roastedPass, hasRoasted := TLVList.Bytes(wire.LoginTLVTagsRoastedPassword); hasRoasted { loginOK = user.ValidateRoastedPass(roastedPass) } if !loginOK { @@ -346,9 +346,9 @@ func (s AuthService) loginSuccessResponse(screenName state.DisplayScreenName, er return wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsScreenName, screenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, net.JoinHostPort(s.config.OSCARHost, s.config.BOSPort)), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, cookie), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, screenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, net.JoinHostPort(s.config.OSCARHost, s.config.BOSPort)), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, cookie), }, }, nil } @@ -356,8 +356,8 @@ func (s AuthService) loginSuccessResponse(screenName state.DisplayScreenName, er func loginFailureResponse(screenName state.DisplayScreenName, code uint16) wire.TLVRestBlock { return wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsScreenName, screenName), - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, code), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, screenName), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, code), }, } } diff --git a/foodgroup/auth_test.go b/foodgroup/auth_test.go index a1cc8be1..8724c3f1 100644 --- a/foodgroup/auth_test.go +++ b/foodgroup/auth_test.go @@ -49,8 +49,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x02_BUCPLoginRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsPasswordHash, user.StrongMD5Pass), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsPasswordHash, user.StrongMD5Pass), }, }, }, @@ -87,9 +87,9 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), }, }, }, @@ -104,9 +104,9 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x02_BUCPLoginRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsClientIdentity, "ICQ 2000b"), - wire.NewTLV(wire.LoginTLVTagsPasswordHash, user.StrongMD5Pass), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsClientIdentity, "ICQ 2000b"), + wire.NewTLVBE(wire.LoginTLVTagsPasswordHash, user.StrongMD5Pass), }, }, }, @@ -143,9 +143,9 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), }, }, }, @@ -160,8 +160,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x02_BUCPLoginRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsPasswordHash, []byte("bad_password")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsPasswordHash, []byte("bad_password")), }, }, }, @@ -183,8 +183,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidPassword), }, }, }, @@ -199,8 +199,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x02_BUCPLoginRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsPasswordHash, []byte("password")), - wire.NewTLV(wire.LoginTLVTagsScreenName, []byte("non_existent_screen_name")), + wire.NewTLVBE(wire.LoginTLVTagsPasswordHash, []byte("password")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, []byte("non_existent_screen_name")), }, }, }, @@ -222,8 +222,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsScreenName, state.NewIdentScreenName("non_existent_screen_name")), - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidUsernameOrPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, state.NewIdentScreenName("non_existent_screen_name")), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidUsernameOrPassword), }, }, }, @@ -238,8 +238,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x02_BUCPLoginRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsPasswordHash, []byte("password")), - wire.NewTLV(wire.LoginTLVTagsScreenName, []byte("100003")), + wire.NewTLVBE(wire.LoginTLVTagsPasswordHash, []byte("password")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, []byte("100003")), }, }, }, @@ -261,8 +261,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsScreenName, state.NewIdentScreenName("100003")), - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, wire.LoginErrICQUserErr), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, state.NewIdentScreenName("100003")), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrICQUserErr), }, }, }, @@ -278,8 +278,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x02_BUCPLoginRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsPasswordHash, user.StrongMD5Pass), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsPasswordHash, user.StrongMD5Pass), }, }, }, @@ -324,9 +324,9 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), }, }, }, @@ -342,8 +342,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x02_BUCPLoginRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsPasswordHash, []byte("bad-password-hash")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsPasswordHash, []byte("bad-password-hash")), }, }, }, @@ -383,9 +383,9 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), }, }, }, @@ -396,8 +396,8 @@ func TestAuthService_BUCPLoginRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x02_BUCPLoginRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsPasswordHash, user.StrongMD5Pass), - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsPasswordHash, user.StrongMD5Pass), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), }, }, }, @@ -486,8 +486,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { inputSNAC: wire.FLAPSignonFrame{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsRoastedPassword, roastedPassword), - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsRoastedPassword, roastedPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), }, }, }, @@ -518,9 +518,9 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { }, expectOutput: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), }, }, }, @@ -533,9 +533,9 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { inputSNAC: wire.FLAPSignonFrame{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsClientIdentity, "ICQ 2000b"), - wire.NewTLV(wire.LoginTLVTagsRoastedPassword, roastedPassword), - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsClientIdentity, "ICQ 2000b"), + wire.NewTLVBE(wire.LoginTLVTagsRoastedPassword, roastedPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), }, }, }, @@ -566,9 +566,9 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { }, expectOutput: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), }, }, }, @@ -581,8 +581,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { inputSNAC: wire.FLAPSignonFrame{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsRoastedPassword, []byte("bad_roasted_password")), - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsRoastedPassword, []byte("bad_roasted_password")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), }, }, }, @@ -598,8 +598,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { }, expectOutput: wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidPassword), }, }, }, @@ -612,8 +612,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { inputSNAC: wire.FLAPSignonFrame{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsRoastedPassword, roastedPassword), - wire.NewTLV(wire.LoginTLVTagsScreenName, []byte("non_existent_screen_name")), + wire.NewTLVBE(wire.LoginTLVTagsRoastedPassword, roastedPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, []byte("non_existent_screen_name")), }, }, }, @@ -629,8 +629,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { }, expectOutput: wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsScreenName, state.NewIdentScreenName("non_existent_screen_name")), - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidUsernameOrPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, state.NewIdentScreenName("non_existent_screen_name")), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrInvalidUsernameOrPassword), }, }, }, @@ -643,9 +643,9 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { inputSNAC: wire.FLAPSignonFrame{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsClientIdentity, "ICQ 2000b"), - wire.NewTLV(wire.LoginTLVTagsRoastedPassword, roastedPassword), - wire.NewTLV(wire.LoginTLVTagsScreenName, []byte("100003")), + wire.NewTLVBE(wire.LoginTLVTagsClientIdentity, "ICQ 2000b"), + wire.NewTLVBE(wire.LoginTLVTagsRoastedPassword, roastedPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, []byte("100003")), }, }, }, @@ -661,8 +661,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { }, expectOutput: wire.TLVRestBlock{ TLVList: []wire.TLV{ - wire.NewTLV(wire.LoginTLVTagsScreenName, state.NewIdentScreenName("100003")), - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, wire.LoginErrICQUserErr), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, state.NewIdentScreenName("100003")), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, wire.LoginErrICQUserErr), }, }, }, @@ -676,8 +676,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { inputSNAC: wire.FLAPSignonFrame{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsRoastedPassword, roastedPassword), - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsRoastedPassword, roastedPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), }, }, }, @@ -716,9 +716,9 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { }, expectOutput: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), }, }, }, @@ -732,8 +732,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { inputSNAC: wire.FLAPSignonFrame{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsRoastedPassword, "bad-roasted-password"), - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsRoastedPassword, "bad-roasted-password"), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), }, }, }, @@ -767,9 +767,9 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { }, expectOutput: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), - wire.NewTLV(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.LoginTLVTagsAuthorizationCookie, []byte("the-cookie")), }, }, }, @@ -778,8 +778,8 @@ func TestAuthService_FLAPLoginResponse(t *testing.T) { inputSNAC: wire.FLAPSignonFrame{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsRoastedPassword, roastedPassword), - wire.NewTLV(wire.LoginTLVTagsScreenName, user.DisplayScreenName), + wire.NewTLVBE(wire.LoginTLVTagsRoastedPassword, roastedPassword), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, user.DisplayScreenName), }, }, }, @@ -856,7 +856,7 @@ func TestAuthService_BUCPChallengeRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x06_BUCPChallengeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, "sn_user_a"), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, "sn_user_a"), }, }, }, @@ -893,7 +893,7 @@ func TestAuthService_BUCPChallengeRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x06_BUCPChallengeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, "sn_user_b"), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, "sn_user_b"), }, }, }, @@ -926,7 +926,7 @@ func TestAuthService_BUCPChallengeRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x06_BUCPChallengeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, "sn_user_b"), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, "sn_user_b"), }, }, }, @@ -948,7 +948,7 @@ func TestAuthService_BUCPChallengeRequest(t *testing.T) { Body: wire.SNAC_0x17_0x03_BUCPLoginResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsErrorSubcode, uint16(0x01)), + wire.NewTLVBE(wire.LoginTLVTagsErrorSubcode, uint16(0x01)), }, }, }, @@ -959,7 +959,7 @@ func TestAuthService_BUCPChallengeRequest(t *testing.T) { inputSNAC: wire.SNAC_0x17_0x06_BUCPChallengeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LoginTLVTagsScreenName, "sn_user_b"), + wire.NewTLVBE(wire.LoginTLVTagsScreenName, "sn_user_b"), }, }, }, diff --git a/foodgroup/buddy.go b/foodgroup/buddy.go index f0d131fc..ebdcc5b0 100644 --- a/foodgroup/buddy.go +++ b/foodgroup/buddy.go @@ -42,10 +42,10 @@ func (s BuddyService) RightsQuery(_ context.Context, frameIn wire.SNACFrame) wir Body: wire.SNAC_0x03_0x03_BuddyRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.BuddyTLVTagsParmMaxBuddies, uint16(100)), - wire.NewTLV(wire.BuddyTLVTagsParmMaxWatchers, uint16(100)), - wire.NewTLV(wire.BuddyTLVTagsParmMaxIcqBroad, uint16(100)), - wire.NewTLV(wire.BuddyTLVTagsParmMaxTempBuddies, uint16(100)), + wire.NewTLVBE(wire.BuddyTLVTagsParmMaxBuddies, uint16(100)), + wire.NewTLVBE(wire.BuddyTLVTagsParmMaxWatchers, uint16(100)), + wire.NewTLVBE(wire.BuddyTLVTagsParmMaxIcqBroad, uint16(100)), + wire.NewTLVBE(wire.BuddyTLVTagsParmMaxTempBuddies, uint16(100)), }, }, }, @@ -89,7 +89,7 @@ func (s BuddyService) UnicastBuddyArrived(ctx context.Context, from *state.Sessi case err != nil: return err case icon != nil: - userInfo.Append(wire.NewTLV(wire.OServiceUserInfoBARTInfo, *icon)) + userInfo.Append(wire.NewTLVBE(wire.OServiceUserInfoBARTInfo, *icon)) } s.messageRelayer.RelayToScreenName(ctx, to.IdentScreenName(), wire.SNACMessage{ Frame: wire.SNACFrame{ @@ -124,7 +124,7 @@ func (s BuddyService) BroadcastBuddyArrived(ctx context.Context, sess *state.Ses case err != nil: return err case icon != nil: - userInfo.Append(wire.NewTLV(wire.OServiceUserInfoBARTInfo, *icon)) + userInfo.Append(wire.NewTLVBE(wire.OServiceUserInfoBARTInfo, *icon)) } s.messageRelayer.RelayToScreenNames(ctx, recipients, wire.SNACMessage{ @@ -164,7 +164,7 @@ func (s BuddyService) BroadcastBuddyDeparted(ctx context.Context, sess *state.Se TLVList: wire.TLVList{ // this TLV needs to be set in order for departure // events to work in ICQ - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0)), }, }, }, diff --git a/foodgroup/buddy_test.go b/foodgroup/buddy_test.go index 13e29003..031a0ce4 100644 --- a/foodgroup/buddy_test.go +++ b/foodgroup/buddy_test.go @@ -24,10 +24,10 @@ func TestBuddyService_RightsQuery(t *testing.T) { Body: wire.SNAC_0x03_0x03_BuddyRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.BuddyTLVTagsParmMaxBuddies, uint16(100)), - wire.NewTLV(wire.BuddyTLVTagsParmMaxWatchers, uint16(100)), - wire.NewTLV(wire.BuddyTLVTagsParmMaxIcqBroad, uint16(100)), - wire.NewTLV(wire.BuddyTLVTagsParmMaxTempBuddies, uint16(100)), + wire.NewTLVBE(wire.BuddyTLVTagsParmMaxBuddies, uint16(100)), + wire.NewTLVBE(wire.BuddyTLVTagsParmMaxWatchers, uint16(100)), + wire.NewTLVBE(wire.BuddyTLVTagsParmMaxIcqBroad, uint16(100)), + wire.NewTLVBE(wire.BuddyTLVTagsParmMaxTempBuddies, uint16(100)), }, }, }, @@ -442,7 +442,7 @@ func TestBuddyService_BroadcastDeparture(t *testing.T) { WarningLevel: 0, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0)), }, }, }, @@ -612,7 +612,7 @@ func TestBuddyService_UnicastBuddyArrived(t *testing.T) { Name: strconv.Itoa(int(wire.BARTTypesBuddyIcon)), TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: []byte{'t', 'h', 'e', 'h', 'a', 's', 'h'}, }), }, diff --git a/foodgroup/chat.go b/foodgroup/chat.go index bd866a19..fb511455 100644 --- a/foodgroup/chat.go +++ b/foodgroup/chat.go @@ -32,7 +32,7 @@ func (s ChatService) ChannelMsgToHost(ctx context.Context, sess *state.Session, SubGroup: wire.ChatChannelMsgToClient, } - msg, hasMessage := inBody.Slice(wire.ChatTLVMessageInformation) + msg, hasMessage := inBody.Bytes(wire.ChatTLVMessageInformation) if !hasMessage { return nil, errors.New("SNAC(0x0E,0x05) does not contain a message TLV") } @@ -44,9 +44,9 @@ func (s ChatService) ChannelMsgToHost(ctx context.Context, sess *state.Session, TLVList: wire.TLVList{ // The order of these TLVs matters for AIM 2.x. if out of // order, screen names do not appear with each chat message. - wire.NewTLV(wire.ChatTLVSenderInformation, sess.TLVUserInfo()), - wire.NewTLV(wire.ChatTLVPublicWhisperFlag, []byte{}), - wire.NewTLV(wire.ChatTLVMessageInformation, msg), + wire.NewTLVBE(wire.ChatTLVSenderInformation, sess.TLVUserInfo()), + wire.NewTLVBE(wire.ChatTLVPublicWhisperFlag, []byte{}), + wire.NewTLVBE(wire.ChatTLVMessageInformation, msg), }, }, } @@ -63,7 +63,7 @@ func (s ChatService) ChannelMsgToHost(ctx context.Context, sess *state.Session, }) var ret *wire.SNACMessage - if _, ackMsg := inBody.Slice(wire.ChatTLVEnableReflectionFlag); ackMsg { + if _, ackMsg := inBody.Bytes(wire.ChatTLVEnableReflectionFlag); ackMsg { // reflect the message back to the sender ret = &wire.SNACMessage{ Frame: frameOut, diff --git a/foodgroup/chat_nav.go b/foodgroup/chat_nav.go index 4eac9b30..5f014339 100644 --- a/foodgroup/chat_nav.go +++ b/foodgroup/chat_nav.go @@ -12,15 +12,15 @@ import ( var defaultExchangeCfg = wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatRoomTLVClassPerms, uint16(0x0010)), - wire.NewTLV(wire.ChatRoomTLVMaxNameLen, uint16(100)), - wire.NewTLV(wire.ChatRoomTLVFlags, uint16(15)), - wire.NewTLV(wire.ChatRoomTLVNavCreatePerms, uint8(2)), - wire.NewTLV(wire.ChatRoomTLVCharSet1, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang1, "en"), - wire.NewTLV(wire.ChatRoomTLVCharSet2, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang2, "en"), + wire.NewTLVBE(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatRoomTLVClassPerms, uint16(0x0010)), + wire.NewTLVBE(wire.ChatRoomTLVMaxNameLen, uint16(100)), + wire.NewTLVBE(wire.ChatRoomTLVFlags, uint16(15)), + wire.NewTLVBE(wire.ChatRoomTLVNavCreatePerms, uint8(2)), + wire.NewTLVBE(wire.ChatRoomTLVCharSet1, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang1, "en"), + wire.NewTLVBE(wire.ChatRoomTLVCharSet2, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang2, "en"), }, } @@ -58,12 +58,12 @@ func (s ChatNavService) RequestChatRights(_ context.Context, inFrame wire.SNACFr Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ + wire.NewTLVBE(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ Identifier: state.PrivateExchange, TLVBlock: defaultExchangeCfg, }), - wire.NewTLV(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ + wire.NewTLVBE(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ Identifier: state.PublicExchange, TLVBlock: defaultExchangeCfg, }), @@ -118,7 +118,7 @@ func (s ChatNavService) CreateRoom(_ context.Context, sess *state.Session, inFra Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatNavTLVRoomInfo, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ + wire.NewTLVBE(wire.ChatNavTLVRoomInfo, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ Cookie: room.Cookie(), Exchange: room.Exchange(), DetailLevel: room.DetailLevel(), @@ -159,7 +159,7 @@ func (s ChatNavService) RequestRoomInfo(_ context.Context, inFrame wire.SNACFram Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatNavTLVRoomInfo, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ + wire.NewTLVBE(wire.ChatNavTLVRoomInfo, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ Cookie: room.Cookie(), Exchange: room.Exchange(), DetailLevel: room.DetailLevel(), @@ -188,8 +188,8 @@ func (s ChatNavService) ExchangeInfo(_ context.Context, inFrame wire.SNACFrame, Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ + wire.NewTLVBE(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ Identifier: inBody.Exchange, TLVBlock: defaultExchangeCfg, }), diff --git a/foodgroup/chat_nav_test.go b/foodgroup/chat_nav_test.go index e3162df5..ff0c8cbe 100644 --- a/foodgroup/chat_nav_test.go +++ b/foodgroup/chat_nav_test.go @@ -41,7 +41,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { DetailLevel: basicChatRoom.DetailLevel(), TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), }, }, }, @@ -55,7 +55,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV( + wire.NewTLVBE( wire.ChatNavRequestRoomInfo, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ Exchange: basicChatRoom.Exchange(), @@ -98,7 +98,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { DetailLevel: basicChatRoom.DetailLevel(), TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), }, }, }, @@ -112,7 +112,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV( + wire.NewTLVBE( wire.ChatNavRequestRoomInfo, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ Exchange: basicChatRoom.Exchange(), @@ -163,7 +163,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { DetailLevel: publicChatRoom.DetailLevel(), TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVRoomName, publicChatRoom.Name()), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, publicChatRoom.Name()), }, }, }, @@ -177,7 +177,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV( + wire.NewTLVBE( wire.ChatNavRequestRoomInfo, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ Exchange: publicChatRoom.Exchange(), @@ -220,7 +220,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { DetailLevel: publicChatRoom.DetailLevel(), TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVRoomName, publicChatRoom.Name()), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, publicChatRoom.Name()), }, }, }, @@ -265,7 +265,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { DetailLevel: basicChatRoom.DetailLevel(), TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), }, }, }, @@ -317,7 +317,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { DetailLevel: basicChatRoom.DetailLevel(), TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), }, }, }, @@ -360,7 +360,7 @@ func TestChatNavService_CreateRoom(t *testing.T) { DetailLevel: basicChatRoom.DetailLevel(), TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, basicChatRoom.Name()), }, }, }, @@ -437,7 +437,7 @@ func TestChatNavService_RequestRoomInfo(t *testing.T) { Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x04, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ + wire.NewTLVBE(0x04, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ Cookie: privateChatRoom.Cookie(), DetailLevel: privateChatRoom.DetailLevel(), Exchange: privateChatRoom.Exchange(), @@ -481,7 +481,7 @@ func TestChatNavService_RequestRoomInfo(t *testing.T) { Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x04, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ + wire.NewTLVBE(0x04, wire.SNAC_0x0E_0x02_ChatRoomInfoUpdate{ Cookie: publicChatRoom.Cookie(), DetailLevel: publicChatRoom.DetailLevel(), Exchange: publicChatRoom.Exchange(), @@ -611,36 +611,36 @@ func TestChatNavService_RequestChatRights(t *testing.T) { Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ + wire.NewTLVBE(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ Identifier: 4, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatRoomTLVClassPerms, uint16(0x0010)), - wire.NewTLV(wire.ChatRoomTLVMaxNameLen, uint16(100)), - wire.NewTLV(wire.ChatRoomTLVFlags, uint16(15)), - wire.NewTLV(wire.ChatRoomTLVNavCreatePerms, uint8(2)), - wire.NewTLV(wire.ChatRoomTLVCharSet1, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang1, "en"), - wire.NewTLV(wire.ChatRoomTLVCharSet2, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang2, "en"), + wire.NewTLVBE(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatRoomTLVClassPerms, uint16(0x0010)), + wire.NewTLVBE(wire.ChatRoomTLVMaxNameLen, uint16(100)), + wire.NewTLVBE(wire.ChatRoomTLVFlags, uint16(15)), + wire.NewTLVBE(wire.ChatRoomTLVNavCreatePerms, uint8(2)), + wire.NewTLVBE(wire.ChatRoomTLVCharSet1, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang1, "en"), + wire.NewTLVBE(wire.ChatRoomTLVCharSet2, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang2, "en"), }, }, }), - wire.NewTLV(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ + wire.NewTLVBE(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ Identifier: 5, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatRoomTLVClassPerms, uint16(0x0010)), - wire.NewTLV(wire.ChatRoomTLVMaxNameLen, uint16(100)), - wire.NewTLV(wire.ChatRoomTLVFlags, uint16(15)), - wire.NewTLV(wire.ChatRoomTLVNavCreatePerms, uint8(2)), - wire.NewTLV(wire.ChatRoomTLVCharSet1, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang1, "en"), - wire.NewTLV(wire.ChatRoomTLVCharSet2, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang2, "en"), + wire.NewTLVBE(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatRoomTLVClassPerms, uint16(0x0010)), + wire.NewTLVBE(wire.ChatRoomTLVMaxNameLen, uint16(100)), + wire.NewTLVBE(wire.ChatRoomTLVFlags, uint16(15)), + wire.NewTLVBE(wire.ChatRoomTLVNavCreatePerms, uint8(2)), + wire.NewTLVBE(wire.ChatRoomTLVCharSet1, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang1, "en"), + wire.NewTLVBE(wire.ChatRoomTLVCharSet2, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang2, "en"), }, }, }), @@ -679,20 +679,20 @@ func TestChatNavService_ExchangeInfo(t *testing.T) { Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ + wire.NewTLVBE(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ Identifier: state.PrivateExchange, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatRoomTLVClassPerms, uint16(0x0010)), - wire.NewTLV(wire.ChatRoomTLVMaxNameLen, uint16(100)), - wire.NewTLV(wire.ChatRoomTLVFlags, uint16(15)), - wire.NewTLV(wire.ChatRoomTLVNavCreatePerms, uint8(2)), - wire.NewTLV(wire.ChatRoomTLVCharSet1, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang1, "en"), - wire.NewTLV(wire.ChatRoomTLVCharSet2, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang2, "en"), + wire.NewTLVBE(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatRoomTLVClassPerms, uint16(0x0010)), + wire.NewTLVBE(wire.ChatRoomTLVMaxNameLen, uint16(100)), + wire.NewTLVBE(wire.ChatRoomTLVFlags, uint16(15)), + wire.NewTLVBE(wire.ChatRoomTLVNavCreatePerms, uint8(2)), + wire.NewTLVBE(wire.ChatRoomTLVCharSet1, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang1, "en"), + wire.NewTLVBE(wire.ChatRoomTLVCharSet2, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang2, "en"), }, }, }), @@ -720,20 +720,20 @@ func TestChatNavService_ExchangeInfo(t *testing.T) { Body: wire.SNAC_0x0D_0x09_ChatNavNavInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ + wire.NewTLVBE(wire.ChatNavTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatNavTLVExchangeInfo, wire.SNAC_0x0D_0x09_TLVExchangeInfo{ Identifier: state.PublicExchange, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), - wire.NewTLV(wire.ChatRoomTLVClassPerms, uint16(0x0010)), - wire.NewTLV(wire.ChatRoomTLVMaxNameLen, uint16(100)), - wire.NewTLV(wire.ChatRoomTLVFlags, uint16(15)), - wire.NewTLV(wire.ChatRoomTLVNavCreatePerms, uint8(2)), - wire.NewTLV(wire.ChatRoomTLVCharSet1, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang1, "en"), - wire.NewTLV(wire.ChatRoomTLVCharSet2, "us-ascii"), - wire.NewTLV(wire.ChatRoomTLVLang2, "en"), + wire.NewTLVBE(wire.ChatRoomTLVMaxConcurrentRooms, uint8(10)), + wire.NewTLVBE(wire.ChatRoomTLVClassPerms, uint16(0x0010)), + wire.NewTLVBE(wire.ChatRoomTLVMaxNameLen, uint16(100)), + wire.NewTLVBE(wire.ChatRoomTLVFlags, uint16(15)), + wire.NewTLVBE(wire.ChatRoomTLVNavCreatePerms, uint8(2)), + wire.NewTLVBE(wire.ChatRoomTLVCharSet1, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang1, "en"), + wire.NewTLVBE(wire.ChatRoomTLVCharSet2, "us-ascii"), + wire.NewTLVBE(wire.ChatRoomTLVLang2, "en"), }, }, }), diff --git a/foodgroup/chat_test.go b/foodgroup/chat_test.go index b8ef6be5..371ecce8 100644 --- a/foodgroup/chat_test.go +++ b/foodgroup/chat_test.go @@ -74,10 +74,10 @@ func TestChatService_ChannelMsgToHost(t *testing.T) { Channel: 14, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatTLVSenderInformation, + wire.NewTLVBE(wire.ChatTLVSenderInformation, newTestSession("user_sending_chat_msg", sessOptCannedSignonTime).TLVUserInfo()), - wire.NewTLV(wire.ChatTLVPublicWhisperFlag, []byte{}), - wire.NewTLV(wire.ChatTLVMessageInformation, []byte{}), + wire.NewTLVBE(wire.ChatTLVPublicWhisperFlag, []byte{}), + wire.NewTLVBE(wire.ChatTLVMessageInformation, []byte{}), }, }, }, @@ -97,10 +97,10 @@ func TestChatService_ChannelMsgToHost(t *testing.T) { Channel: 14, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatTLVSenderInformation, + wire.NewTLVBE(wire.ChatTLVSenderInformation, newTestSession("user_sending_chat_msg", sessOptCannedSignonTime).TLVUserInfo()), - wire.NewTLV(wire.ChatTLVPublicWhisperFlag, []byte{}), - wire.NewTLV(wire.ChatTLVMessageInformation, []byte{}), + wire.NewTLVBE(wire.ChatTLVPublicWhisperFlag, []byte{}), + wire.NewTLVBE(wire.ChatTLVMessageInformation, []byte{}), }, }, }, @@ -148,10 +148,10 @@ func TestChatService_ChannelMsgToHost(t *testing.T) { Channel: wire.ICBMChannelMIME, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatTLVSenderInformation, + wire.NewTLVBE(wire.ChatTLVSenderInformation, newTestSession("user_sending_chat_msg", sessOptCannedSignonTime).TLVUserInfo()), - wire.NewTLV(wire.ChatTLVPublicWhisperFlag, []byte{}), - wire.NewTLV(wire.ChatTLVMessageInformation, []byte{}), + wire.NewTLVBE(wire.ChatTLVPublicWhisperFlag, []byte{}), + wire.NewTLVBE(wire.ChatTLVMessageInformation, []byte{}), }, }, }, @@ -203,10 +203,10 @@ func TestChatService_ChannelMsgToHost(t *testing.T) { Channel: 14, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ChatTLVSenderInformation, + wire.NewTLVBE(wire.ChatTLVSenderInformation, newTestSession("user_sending_chat_msg", sessOptCannedSignonTime).TLVUserInfo()), - wire.NewTLV(wire.ChatTLVPublicWhisperFlag, []byte{}), - wire.NewTLV(wire.ChatTLVMessageInformation, []byte{}), + wire.NewTLVBE(wire.ChatTLVPublicWhisperFlag, []byte{}), + wire.NewTLVBE(wire.ChatTLVMessageInformation, []byte{}), }, }, }, diff --git a/foodgroup/feedbag.go b/foodgroup/feedbag.go index d6c2daa2..5192ca0e 100644 --- a/foodgroup/feedbag.go +++ b/foodgroup/feedbag.go @@ -71,17 +71,17 @@ func (s FeedbagService) RightsQuery(_ context.Context, inFrame wire.SNACFrame) w Body: wire.SNAC_0x13_0x03_FeedbagRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagRightsMaxItemAttrs, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxItemsByClass, maxItemsByClass), - wire.NewTLV(wire.FeedbagRightsMaxClientItems, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxItemNameLen, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxRecentBuddies, uint16(200)), - wire.NewTLV(wire.FeedbagRightsInteractionBuddies, uint16(200)), - wire.NewTLV(wire.FeedbagRightsInteractionHalfLife, uint16(200)), - wire.NewTLV(wire.FeedbagRightsInteractionMaxScore, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxBuddiesPerGroup, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxMegaBots, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxSmartGroups, uint16(100)), + wire.NewTLVBE(wire.FeedbagRightsMaxItemAttrs, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxItemsByClass, maxItemsByClass), + wire.NewTLVBE(wire.FeedbagRightsMaxClientItems, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxItemNameLen, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxRecentBuddies, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsInteractionBuddies, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsInteractionHalfLife, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsInteractionMaxScore, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxBuddiesPerGroup, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxMegaBots, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxSmartGroups, uint16(100)), }, }, }, @@ -244,7 +244,7 @@ func (s FeedbagService) UpsertItem(ctx context.Context, sess *state.Session, inF // If the icon already exists, tell the user's buddies about the icon change. func (s FeedbagService) broadcastIconUpdate(ctx context.Context, sess *state.Session, item wire.FeedbagItem) error { btlv := wire.BARTInfo{} - if b, hasBuf := item.Slice(wire.FeedbagAttributesBartInfo); hasBuf { + if b, hasBuf := item.Bytes(wire.FeedbagAttributesBartInfo); hasBuf { if err := wire.UnmarshalBE(&btlv, bytes.NewBuffer(b)); err != nil { return err } @@ -364,3 +364,44 @@ func (s FeedbagService) Use(ctx context.Context, sess *state.Session) error { } return nil } + +// RespondAuthorizeToHost forwards an authorization response from the user +// whose authorization was requested to the user who made the authorization +// request. +// Right now we send an ICBM request so that responses can work for both ICQ +// 2000b and ICQ 2001a. This function should eventually only send an ICBM +// message to non-feedbag clients and SNAC(0x0013,0x001B) to feedbag clients. +func (s FeedbagService) RespondAuthorizeToHost(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, inBody wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost) error { + response := wire.ICBMCh4Message{ + UIN: sess.UIN(), + Message: inBody.Reason, + } + + switch inBody.Accepted { + case 0: + response.MessageType = wire.ICBMMsgTypeAuthDeny + case 1: + response.MessageType = wire.ICBMMsgTypeAuthOK + default: + return fmt.Errorf("invalid accepted flag %d", inBody.Accepted) + } + + s.messageRelayer.RelayToScreenName(ctx, state.NewIdentScreenName(inBody.ScreenName), wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICBM, + SubGroup: wire.ICBMChannelMsgToClient, + }, + Body: wire.SNAC_0x04_0x07_ICBMChannelMsgToClient{ + ChannelID: wire.ICBMChannelICQ, + TLVUserInfo: sess.TLVUserInfo(), + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVLE(wire.ICBMTLVData, response), + wire.NewTLVBE(wire.ICBMTLVStore, []byte{}), + }, + }, + }, + }) + + return nil +} diff --git a/foodgroup/feedbag_test.go b/foodgroup/feedbag_test.go index 437c7050..a5279c48 100644 --- a/foodgroup/feedbag_test.go +++ b/foodgroup/feedbag_test.go @@ -327,8 +327,8 @@ func TestFeedbagService_RightsQuery(t *testing.T) { Body: wire.SNAC_0x13_0x03_FeedbagRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagRightsMaxItemAttrs, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxItemsByClass, []uint16{ + wire.NewTLVBE(wire.FeedbagRightsMaxItemAttrs, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxItemsByClass, []uint16{ 61, 61, 100, @@ -351,15 +351,15 @@ func TestFeedbagService_RightsQuery(t *testing.T) { 1, 200, }), - wire.NewTLV(wire.FeedbagRightsMaxClientItems, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxItemNameLen, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxRecentBuddies, uint16(200)), - wire.NewTLV(wire.FeedbagRightsInteractionBuddies, uint16(200)), - wire.NewTLV(wire.FeedbagRightsInteractionHalfLife, uint16(200)), - wire.NewTLV(wire.FeedbagRightsInteractionMaxScore, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxBuddiesPerGroup, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxMegaBots, uint16(200)), - wire.NewTLV(wire.FeedbagRightsMaxSmartGroups, uint16(100)), + wire.NewTLVBE(wire.FeedbagRightsMaxClientItems, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxItemNameLen, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxRecentBuddies, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsInteractionBuddies, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsInteractionHalfLife, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsInteractionMaxScore, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxBuddiesPerGroup, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxMegaBots, uint16(200)), + wire.NewTLVBE(wire.FeedbagRightsMaxSmartGroups, uint16(100)), }, }, }, @@ -750,7 +750,7 @@ func TestFeedbagService_UpsertItem(t *testing.T) { ClassID: wire.FeedbagClassIdBart, TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: []byte{'t', 'h', 'e', 'h', 'a', 's', 'h'}, }), }, @@ -777,7 +777,7 @@ func TestFeedbagService_UpsertItem(t *testing.T) { ClassID: wire.FeedbagClassIdBart, TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: []byte{'t', 'h', 'e', 'h', 'a', 's', 'h'}, }), }, @@ -834,7 +834,7 @@ func TestFeedbagService_UpsertItem(t *testing.T) { ClassID: wire.FeedbagClassIdBart, TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: []byte{'t', 'h', 'e', 'h', 'a', 's', 'h'}, }), }, @@ -861,7 +861,7 @@ func TestFeedbagService_UpsertItem(t *testing.T) { ClassID: wire.FeedbagClassIdBart, TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: []byte{'t', 'h', 'e', 'h', 'a', 's', 'h'}, }), }, @@ -927,7 +927,7 @@ func TestFeedbagService_UpsertItem(t *testing.T) { ClassID: wire.FeedbagClassIdBart, TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: wire.GetClearIconHash(), }), }, @@ -946,7 +946,7 @@ func TestFeedbagService_UpsertItem(t *testing.T) { ClassID: wire.FeedbagClassIdBart, TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: wire.GetClearIconHash(), }), }, @@ -1441,3 +1441,101 @@ func TestFeedbagService_Use(t *testing.T) { }) } } + +func TestFeedbagService_RespondAuthorizeToHost(t *testing.T) { + tests := []struct { + name string + sess *state.Session + bodyIn wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost + mockParams mockParams + wantErr error + }{ + { + name: "authorization accepted", + sess: newTestSession("100001", sessOptUIN(100001)), + bodyIn: wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost{ + ScreenName: "100003", + Accepted: 1, + }, + mockParams: mockParams{ + messageRelayerParams: messageRelayerParams{ + relayToScreenNameParams: relayToScreenNameParams{ + { + screenName: state.NewIdentScreenName("100003"), + message: wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICBM, + SubGroup: wire.ICBMChannelMsgToClient, + }, + Body: wire.SNAC_0x04_0x07_ICBMChannelMsgToClient{ + ChannelID: wire.ICBMChannelICQ, + TLVUserInfo: newTestSession("100001").TLVUserInfo(), + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVLE(wire.ICBMTLVData, wire.ICBMCh4Message{ + UIN: 100001, + MessageType: wire.ICBMMsgTypeAuthOK, + }), + wire.NewTLVBE(wire.ICBMTLVStore, []byte{}), + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "authorization denied (with reason)", + sess: newTestSession("100001", sessOptUIN(100001)), + bodyIn: wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost{ + ScreenName: "100003", + Accepted: 0, + Reason: "I don't know you!", + }, + mockParams: mockParams{ + messageRelayerParams: messageRelayerParams{ + relayToScreenNameParams: relayToScreenNameParams{ + { + screenName: state.NewIdentScreenName("100003"), + message: wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICBM, + SubGroup: wire.ICBMChannelMsgToClient, + }, + Body: wire.SNAC_0x04_0x07_ICBMChannelMsgToClient{ + ChannelID: wire.ICBMChannelICQ, + TLVUserInfo: newTestSession("100001").TLVUserInfo(), + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVLE(wire.ICBMTLVData, wire.ICBMCh4Message{ + UIN: 100001, + MessageType: wire.ICBMMsgTypeAuthDeny, + Message: "I don't know you!", + }), + wire.NewTLVBE(wire.ICBMTLVStore, []byte{}), + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + messageRelayer := newMockMessageRelayer(t) + for _, params := range tt.mockParams.relayToScreenNameParams { + messageRelayer.EXPECT(). + RelayToScreenName(nil, params.screenName, params.message) + } + + svc := NewFeedbagService(slog.Default(), messageRelayer, nil, nil, nil) + haveErr := svc.RespondAuthorizeToHost(nil, tt.sess, wire.SNACFrame{}, tt.bodyIn) + assert.ErrorIs(t, tt.wantErr, haveErr) + }) + } +} diff --git a/foodgroup/icbm.go b/foodgroup/icbm.go index 6c9c6f25..d00ba7a6 100644 --- a/foodgroup/icbm.go +++ b/foodgroup/icbm.go @@ -91,7 +91,7 @@ func (s ICBMService) ChannelMsgToHost(ctx context.Context, sess *state.Session, recipSess := s.messageRelayer.RetrieveByScreenName(recip) if recipSess == nil { // todo: verify user exists, otherwise this could save a bunch of garbage records - if _, saveOffline := inBody.Slice(wire.ICBMTLVStore); saveOffline { + if _, saveOffline := inBody.Bytes(wire.ICBMTLVStore); saveOffline { offlineMsg := state.OfflineMessage{ Message: inBody, Recipient: recip, @@ -146,7 +146,7 @@ func (s ICBMService) ChannelMsgToHost(ctx context.Context, sess *state.Session, Body: clientIM, }) - if _, requestedConfirmation := inBody.TLVRestBlock.Slice(wire.ICBMTLVRequestHostAck); !requestedConfirmation { + if _, requestedConfirmation := inBody.TLVRestBlock.Bytes(wire.ICBMTLVRequestHostAck); !requestedConfirmation { // don't ack message return nil, nil } diff --git a/foodgroup/icbm_test.go b/foodgroup/icbm_test.go index 465a5ef5..86002ddc 100644 --- a/foodgroup/icbm_test.go +++ b/foodgroup/icbm_test.go @@ -243,8 +243,8 @@ func TestICBMService_ChannelMsgToHost(t *testing.T) { ScreenName: "22222222", TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICBMTLVRequestHostAck, []byte{}), - wire.NewTLV(wire.ICBMTLVStore, []byte{}), + wire.NewTLVBE(wire.ICBMTLVRequestHostAck, []byte{}), + wire.NewTLVBE(wire.ICBMTLVStore, []byte{}), }, }, }, @@ -271,8 +271,8 @@ func TestICBMService_ChannelMsgToHost(t *testing.T) { ScreenName: "22222222", TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICBMTLVRequestHostAck, []byte{}), - wire.NewTLV(wire.ICBMTLVStore, []byte{}), + wire.NewTLVBE(wire.ICBMTLVRequestHostAck, []byte{}), + wire.NewTLVBE(wire.ICBMTLVStore, []byte{}), }, }, }, diff --git a/foodgroup/icq.go b/foodgroup/icq.go index 6b024a30..46cbce5b 100644 --- a/foodgroup/icq.go +++ b/foodgroup/icq.go @@ -128,6 +128,46 @@ func (s ICQService) FindByEmail(ctx context.Context, sess *state.Session, req wi }) } +func (s ICQService) FindByEmail3(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3, seq uint16) error { + b, hasEmail := req.Bytes(wire.ICQTLVTagsEmail) + if !hasEmail { + return errors.New("unable to get email from request") + } + + email := wire.ICQEmail{} + if err := wire.UnmarshalLE(&email, bytes.NewReader(b)); err != nil { + return fmt.Errorf("unmarshal email: %w", err) + } + + resp := wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ + ICQMetadata: wire.ICQMetadata{ + UIN: sess.UIN(), + ReqType: wire.ICQDBQueryMetaReply, + Seq: seq, + }, + ReqSubType: wire.ICQDBQueryMetaReplyLastUserFound, + Success: wire.ICQStatusCodeOK, + } + resp.LastResult() + + res, err := s.userFinder.FindByEmail(email.Email) + + switch { + case errors.Is(err, state.ErrNoUser): + resp.Success = wire.ICQStatusCodeFail + case err != nil: + s.logger.Error("FindByEmail failed", "err", err.Error()) + resp.Success = wire.ICQStatusCodeErr + default: + resp.Success = wire.ICQStatusCodeOK + resp.Details = s.createResult(res) + } + + return s.reply(ctx, sess, wire.ICQMessageReplyEnvelope{ + Message: resp, + }) +} + func (s ICQService) FindByInterests(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages, seq uint16) error { resp := wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ ICQMetadata: wire.ICQMetadata{ @@ -173,6 +213,74 @@ func (s ICQService) FindByInterests(ctx context.Context, sess *state.Session, re return nil } +func (s ICQService) FindByWhitePages2(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2, seq uint16) error { + + users, err := func() ([]state.User, error) { + if keyword, hasKeyword := req.ICQString(wire.ICQTLVTagsWhitepagesSearchKeywords); hasKeyword { + res, err := s.userFinder.FindByKeyword(keyword) + if err != nil { + return nil, fmt.Errorf("FindByKeyword failed: %w", err) + } + return res, nil + } + + bNick, hasNick := req.ICQString(wire.ICQTLVTagsNickname) + bFirst, hasFirst := req.ICQString(wire.ICQTLVTagsFirstName) + bLast, hastLast := req.ICQString(wire.ICQTLVTagsLastName) + + if hasNick || hasFirst || hastLast { + res, err := s.userFinder.FindByDetails(bFirst, bLast, bNick) + if err != nil { + return nil, fmt.Errorf("FindByDetails failed: %w", err) + } + return res, nil + } + + return nil, nil + }() + + resp := wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ + ICQMetadata: wire.ICQMetadata{ + UIN: sess.UIN(), + ReqType: wire.ICQDBQueryMetaReply, + Seq: seq, + }, + Success: wire.ICQStatusCodeOK, + ReqSubType: wire.ICQDBQueryMetaReplyLastUserFound, + } + + if err != nil { + s.logger.Error("FindByWhitePages2 failed", "err", err.Error()) + resp.Success = wire.ICQStatusCodeErr + return s.reply(ctx, sess, wire.ICQMessageReplyEnvelope{ + Message: resp, + }) + } + + if len(users) == 0 { + resp.Success = wire.ICQStatusCodeFail + return s.reply(ctx, sess, wire.ICQMessageReplyEnvelope{ + Message: resp, + }) + } + + for i := 0; i < len(users); i++ { + if i == len(users)-1 { + resp.LastResult() + } else { + resp.ReqSubType = wire.ICQDBQueryMetaReplyUserFound + } + resp.Details = s.createResult(users[i]) + if err := s.reply(ctx, sess, wire.ICQMessageReplyEnvelope{ + Message: resp, + }); err != nil { + return err + } + } + + return nil +} + func (s ICQService) FindByUIN(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN, seq uint16) error { resp := wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ ICQMetadata: wire.ICQMetadata{ @@ -203,6 +311,41 @@ func (s ICQService) FindByUIN(ctx context.Context, sess *state.Session, req wire }) } +func (s ICQService) FindByUIN2(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2, seq uint16) error { + UIN, hasUIN := req.Uint32LE(wire.ICQTLVTagsUIN) + if !hasUIN { + return errors.New("unable to get UIN from request") + } + + resp := wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ + ICQMetadata: wire.ICQMetadata{ + UIN: sess.UIN(), + ReqType: wire.ICQDBQueryMetaReply, + Seq: seq, + }, + ReqSubType: wire.ICQDBQueryMetaReplyLastUserFound, + Success: wire.ICQStatusCodeOK, + } + resp.LastResult() + + res, err := s.userFinder.FindByUIN(UIN) + + switch { + case errors.Is(err, state.ErrNoUser): + resp.Success = wire.ICQStatusCodeFail + case err != nil: + s.logger.Error("FindByUIN failed", "err", err.Error()) + resp.Success = wire.ICQStatusCodeErr + default: + resp.Success = wire.ICQStatusCodeOK + resp.Details = s.createResult(res) + } + + return s.reply(ctx, sess, wire.ICQMessageReplyEnvelope{ + Message: resp, + }) +} + func (s ICQService) FullUserInfo(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN, seq uint16) error { user, err := s.userFinder.FindByUIN(req.UIN) @@ -267,7 +410,7 @@ func (s ICQService) OfflineMsgReq(ctx context.Context, sess *state.Session, seq switch msgIn.Message.ChannelID { case wire.ICBMChannelIM: - if payload, hasIM := msgIn.Message.Slice(wire.ICBMTLVAOLIMData); hasIM { + if payload, hasIM := msgIn.Message.Bytes(wire.ICBMTLVAOLIMData); hasIM { // send regular IM msgText, err := wire.UnmarshalICBMMessageText(payload) if err != nil { @@ -277,16 +420,16 @@ func (s ICQService) OfflineMsgReq(ctx context.Context, sess *state.Session, seq reply.Message = msgText } case wire.ICBMChannelICQ: - if b, hasAuthReq := msgIn.Message.Slice(wire.ICBMTLVData); hasAuthReq { + if b, hasAuthReq := msgIn.Message.Bytes(wire.ICBMTLVData); hasAuthReq { // send authorization request - rdv := wire.ICBMCh4Message{} + msg := wire.ICBMCh4Message{} buf := bytes.NewBuffer(b) - if err := wire.UnmarshalLE(&rdv, buf); err != nil { + if err := wire.UnmarshalLE(&msg, buf); err != nil { return err } - reply.MsgType = rdv.MessageType - reply.Flags = rdv.Flags - reply.Message = rdv.Message + reply.MsgType = msg.MessageType + reply.Flags = msg.Flags + reply.Message = msg.Message } } @@ -705,7 +848,7 @@ func (s ICQService) reply(ctx context.Context, sess *state.Session, message wire Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, message), + wire.NewTLVBE(wire.ICQTLVTagsMetadata, message), }, }, }, diff --git a/foodgroup/icq_test.go b/foodgroup/icq_test.go index 2d7546cf..c0a7aaea 100644 --- a/foodgroup/icq_test.go +++ b/foodgroup/icq_test.go @@ -134,7 +134,7 @@ func TestICQService_FindByDetails(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -171,7 +171,7 @@ func TestICQService_FindByDetails(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -311,7 +311,7 @@ func TestICQService_FindByEmail(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -389,13 +389,431 @@ func TestICQService_FindByEmail(t *testing.T) { } } +func TestICQService_FindByEmail3(t *testing.T) { + tests := []struct { + name string + timeNow func() time.Time + seq uint16 + sess *state.Session + req wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3 + mockParams mockParams + wantErr error + }{ + { + name: "happy path", + timeNow: func() time.Time { + return time.Date(2020, time.August, 1, 0, 0, 0, 0, time.UTC) + }, + seq: 1, + sess: newTestSession("11111111", sessOptUIN(11111111)), + req: wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVLE(wire.ICQTLVTagsEmail, wire.ICQEmail{ + Email: "john@example.com", + }), + }, + }, + }, + mockParams: mockParams{ + icqUserFinderParams: icqUserFinderParams{ + findByEmailParams: findByEmailParams{ + { + email: "john@example.com", + result: state.User{ + IdentScreenName: state.NewIdentScreenName("123456789"), + ICQBasicInfo: state.ICQBasicInfo{ + EmailAddress: "john@example.com", + FirstName: "John", + LastName: "Doe", + Nickname: "Johnny", + }, + ICQPermissions: state.ICQPermissions{ + AuthRequired: true, + }, + ICQMoreInfo: state.ICQMoreInfo{ + BirthDay: 31, + BirthMonth: 7, + BirthYear: 1999, + Gender: 1, + }, + }, + }, + }, + }, + messageRelayerParams: messageRelayerParams{ + relayToScreenNameParams: relayToScreenNameParams{ + { + screenName: state.NewIdentScreenName("11111111"), + message: wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICQ, + SubGroup: wire.ICQDBReply, + }, + Body: wire.SNAC_0x15_0x02_DBReply{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ + ICQMetadata: wire.ICQMetadata{ + UIN: 11111111, + ReqType: wire.ICQDBQueryMetaReply, + Seq: 1, + }, + Success: wire.ICQStatusCodeOK, + ReqSubType: wire.ICQDBQueryMetaReplyLastUserFound, + Details: wire.ICQUserSearchRecord{ + UIN: 123456789, + Nickname: "Johnny", + FirstName: "John", + LastName: "Doe", + Email: "john@example.com", + Authorization: 1, + OnlineStatus: 1, + Gender: 1, + Age: 21, + }, + LastMessageFooter: &struct { + FoundUsersLeft uint32 + }{ + FoundUsersLeft: 0, + }, + }, + }), + }, + }, + }, + }, + }, + }, + }, + sessionRetrieverParams: sessionRetrieverParams{ + retrieveSessionParams{ + { + screenName: state.NewIdentScreenName("123456789"), + result: &state.Session{}, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + userFinder := newMockICQUserFinder(t) + for _, params := range tt.mockParams.findByEmailParams { + userFinder.EXPECT(). + FindByEmail(params.email). + Return(params.result, params.err) + } + + messageRelayer := newMockMessageRelayer(t) + for _, params := range tt.mockParams.relayToScreenNameParams { + messageRelayer.EXPECT().RelayToScreenName(mock.Anything, params.screenName, params.message) + } + + sessionRetriever := newMockSessionRetriever(t) + for _, params := range tt.mockParams.retrieveSessionParams { + sessionRetriever.EXPECT(). + RetrieveSession(params.screenName). + Return(params.result) + } + + s := ICQService{ + messageRelayer: messageRelayer, + sessionRetriever: sessionRetriever, + timeNow: tt.timeNow, + userFinder: userFinder, + } + err := s.FindByEmail3(nil, tt.sess, tt.req, tt.seq) + assert.NoError(t, err) + }) + } +} + func TestICQService_FindByUIN(t *testing.T) { tests := []struct { name string timeNow func() time.Time seq uint16 sess *state.Session - req wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN + req wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN + mockParams mockParams + wantErr error + }{ + { + name: "happy path", + timeNow: func() time.Time { + return time.Date(2020, time.August, 1, 0, 0, 0, 0, time.UTC) + }, + seq: 1, + sess: newTestSession("11111111", sessOptUIN(11111111)), + req: wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN{ + UIN: 123456789, + }, + mockParams: mockParams{ + icqUserFinderParams: icqUserFinderParams{ + findByUINParams: findByUINParams{ + { + UIN: 123456789, + result: state.User{ + IdentScreenName: state.NewIdentScreenName("123456789"), + ICQPermissions: state.ICQPermissions{ + AuthRequired: true, + }, + ICQBasicInfo: state.ICQBasicInfo{ + EmailAddress: "john@example.com", + FirstName: "John", + LastName: "Doe", + Nickname: "Johnny", + }, + ICQMoreInfo: state.ICQMoreInfo{ + Gender: 1, + BirthDay: 31, + BirthMonth: 7, + BirthYear: 1999, + }, + }, + }, + }, + }, + messageRelayerParams: messageRelayerParams{ + relayToScreenNameParams: relayToScreenNameParams{ + { + screenName: state.NewIdentScreenName("11111111"), + message: wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICQ, + SubGroup: wire.ICQDBReply, + }, + Body: wire.SNAC_0x15_0x02_DBReply{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ + ICQMetadata: wire.ICQMetadata{ + UIN: 11111111, + ReqType: wire.ICQDBQueryMetaReply, + Seq: 1, + }, + Success: wire.ICQStatusCodeOK, + ReqSubType: wire.ICQDBQueryMetaReplyLastUserFound, + Details: wire.ICQUserSearchRecord{ + UIN: 123456789, + Nickname: "Johnny", + FirstName: "John", + LastName: "Doe", + Email: "john@example.com", + Authorization: 1, + OnlineStatus: 1, + Gender: 1, + Age: 21, + }, + LastMessageFooter: &struct { + FoundUsersLeft uint32 + }{ + FoundUsersLeft: 0, + }, + }, + }), + }, + }, + }, + }, + }, + }, + }, + sessionRetrieverParams: sessionRetrieverParams{ + retrieveSessionParams{ + { + screenName: state.NewIdentScreenName("123456789"), + result: &state.Session{}, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + userFinder := newMockICQUserFinder(t) + for _, params := range tt.mockParams.findByUINParams { + userFinder.EXPECT(). + FindByUIN(params.UIN). + Return(params.result, params.err) + } + + messageRelayer := newMockMessageRelayer(t) + for _, params := range tt.mockParams.relayToScreenNameParams { + messageRelayer.EXPECT().RelayToScreenName(mock.Anything, params.screenName, params.message) + } + + sessionRetriever := newMockSessionRetriever(t) + for _, params := range tt.mockParams.retrieveSessionParams { + sessionRetriever.EXPECT(). + RetrieveSession(params.screenName). + Return(params.result) + } + + s := ICQService{ + messageRelayer: messageRelayer, + sessionRetriever: sessionRetriever, + timeNow: tt.timeNow, + userFinder: userFinder, + } + err := s.FindByUIN(nil, tt.sess, tt.req, tt.seq) + assert.NoError(t, err) + }) + } +} + +func TestICQService_FindByUIN2(t *testing.T) { + tests := []struct { + name string + timeNow func() time.Time + seq uint16 + sess *state.Session + req wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2 + mockParams mockParams + wantErr error + }{ + { + name: "happy path", + timeNow: func() time.Time { + return time.Date(2020, time.August, 1, 0, 0, 0, 0, time.UTC) + }, + seq: 1, + sess: newTestSession("11111111", sessOptUIN(11111111)), + req: wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVLE(wire.ICQTLVTagsUIN, uint32(123456789)), + }, + }, + }, + mockParams: mockParams{ + icqUserFinderParams: icqUserFinderParams{ + findByUINParams: findByUINParams{ + { + UIN: 123456789, + result: state.User{ + IdentScreenName: state.NewIdentScreenName("123456789"), + ICQPermissions: state.ICQPermissions{ + AuthRequired: true, + }, + ICQBasicInfo: state.ICQBasicInfo{ + EmailAddress: "john@example.com", + FirstName: "John", + LastName: "Doe", + Nickname: "Johnny", + }, + ICQMoreInfo: state.ICQMoreInfo{ + Gender: 1, + BirthDay: 31, + BirthMonth: 7, + BirthYear: 1999, + }, + }, + }, + }, + }, + messageRelayerParams: messageRelayerParams{ + relayToScreenNameParams: relayToScreenNameParams{ + { + screenName: state.NewIdentScreenName("11111111"), + message: wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICQ, + SubGroup: wire.ICQDBReply, + }, + Body: wire.SNAC_0x15_0x02_DBReply{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ + ICQMetadata: wire.ICQMetadata{ + UIN: 11111111, + ReqType: wire.ICQDBQueryMetaReply, + Seq: 1, + }, + Success: wire.ICQStatusCodeOK, + ReqSubType: wire.ICQDBQueryMetaReplyLastUserFound, + Details: wire.ICQUserSearchRecord{ + UIN: 123456789, + Nickname: "Johnny", + FirstName: "John", + LastName: "Doe", + Email: "john@example.com", + Authorization: 1, + OnlineStatus: 1, + Gender: 1, + Age: 21, + }, + LastMessageFooter: &struct { + FoundUsersLeft uint32 + }{ + FoundUsersLeft: 0, + }, + }, + }), + }, + }, + }, + }, + }, + }, + }, + sessionRetrieverParams: sessionRetrieverParams{ + retrieveSessionParams{ + { + screenName: state.NewIdentScreenName("123456789"), + result: &state.Session{}, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + userFinder := newMockICQUserFinder(t) + for _, params := range tt.mockParams.findByUINParams { + userFinder.EXPECT(). + FindByUIN(params.UIN). + Return(params.result, params.err) + } + + messageRelayer := newMockMessageRelayer(t) + for _, params := range tt.mockParams.relayToScreenNameParams { + messageRelayer.EXPECT().RelayToScreenName(mock.Anything, params.screenName, params.message) + } + + sessionRetriever := newMockSessionRetriever(t) + for _, params := range tt.mockParams.retrieveSessionParams { + sessionRetriever.EXPECT(). + RetrieveSession(params.screenName). + Return(params.result) + } + + s := ICQService{ + messageRelayer: messageRelayer, + sessionRetriever: sessionRetriever, + timeNow: tt.timeNow, + userFinder: userFinder, + } + err := s.FindByUIN2(nil, tt.sess, tt.req, tt.seq) + assert.NoError(t, err) + }) + } +} + +func TestICQService_FindByWhitePages(t *testing.T) { + tests := []struct { + name string + timeNow func() time.Time + seq uint16 + sess *state.Session + req wire.ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages mockParams mockParams wantErr error }{ @@ -406,30 +824,52 @@ func TestICQService_FindByUIN(t *testing.T) { }, seq: 1, sess: newTestSession("11111111", sessOptUIN(11111111)), - req: wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN{ - UIN: 123456789, + req: wire.ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages{ + InterestsCode: 10, + InterestsKeyword: "knitting,crocheting,sewing", }, mockParams: mockParams{ icqUserFinderParams: icqUserFinderParams{ - findByUINParams: findByUINParams{ + findByInterestsParams: findByInterestsParams{ { - UIN: 123456789, - result: state.User{ - IdentScreenName: state.NewIdentScreenName("123456789"), - ICQPermissions: state.ICQPermissions{ - AuthRequired: true, - }, - ICQBasicInfo: state.ICQBasicInfo{ - EmailAddress: "john@example.com", - FirstName: "John", - LastName: "Doe", - Nickname: "Johnny", + code: 10, + keywords: []string{"knitting", "crocheting", "sewing"}, + result: []state.User{ + { + IdentScreenName: state.NewIdentScreenName("987654321"), + ICQBasicInfo: state.ICQBasicInfo{ + EmailAddress: "janey@example.com", + FirstName: "Jane", + LastName: "Doe", + Nickname: "Janey", + }, + ICQPermissions: state.ICQPermissions{ + AuthRequired: false, + }, + ICQMoreInfo: state.ICQMoreInfo{ + BirthDay: 31, + BirthMonth: 7, + BirthYear: 1995, + Gender: 2, + }, }, - ICQMoreInfo: state.ICQMoreInfo{ - Gender: 1, - BirthDay: 31, - BirthMonth: 7, - BirthYear: 1999, + { + IdentScreenName: state.NewIdentScreenName("123456789"), + ICQBasicInfo: state.ICQBasicInfo{ + EmailAddress: "alice@example.com", + FirstName: "Alice", + LastName: "Smith", + Nickname: "Ally123", + }, + ICQPermissions: state.ICQPermissions{ + AuthRequired: true, + }, + ICQMoreInfo: state.ICQMoreInfo{ + BirthDay: 31, + BirthMonth: 7, + BirthYear: 1999, + Gender: 1, + }, }, }, }, @@ -447,7 +887,44 @@ func TestICQService_FindByUIN(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ + ICQMetadata: wire.ICQMetadata{ + UIN: 11111111, + ReqType: wire.ICQDBQueryMetaReply, + Seq: 1, + }, + Success: wire.ICQStatusCodeOK, + ReqSubType: wire.ICQDBQueryMetaReplyUserFound, + Details: wire.ICQUserSearchRecord{ + UIN: 987654321, + Nickname: "Janey", + FirstName: "Jane", + LastName: "Doe", + Email: "janey@example.com", + Authorization: 0, + OnlineStatus: 0, + Gender: 2, + Age: 25, + }, + }, + }), + }, + }, + }, + }, + }, + { + screenName: state.NewIdentScreenName("11111111"), + message: wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICQ, + SubGroup: wire.ICQDBReply, + }, + Body: wire.SNAC_0x15_0x02_DBReply{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -458,10 +935,10 @@ func TestICQService_FindByUIN(t *testing.T) { ReqSubType: wire.ICQDBQueryMetaReplyLastUserFound, Details: wire.ICQUserSearchRecord{ UIN: 123456789, - Nickname: "Johnny", - FirstName: "John", - LastName: "Doe", - Email: "john@example.com", + Nickname: "Ally123", + FirstName: "Alice", + LastName: "Smith", + Email: "alice@example.com", Authorization: 1, OnlineStatus: 1, Gender: 1, @@ -483,6 +960,10 @@ func TestICQService_FindByUIN(t *testing.T) { }, sessionRetrieverParams: sessionRetrieverParams{ retrieveSessionParams{ + { + screenName: state.NewIdentScreenName("987654321"), + result: nil, + }, { screenName: state.NewIdentScreenName("123456789"), result: &state.Session{}, @@ -495,9 +976,9 @@ func TestICQService_FindByUIN(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { userFinder := newMockICQUserFinder(t) - for _, params := range tt.mockParams.findByUINParams { + for _, params := range tt.mockParams.findByInterestsParams { userFinder.EXPECT(). - FindByUIN(params.UIN). + FindByInterests(params.code, params.keywords). Return(params.result, params.err) } @@ -519,39 +1000,45 @@ func TestICQService_FindByUIN(t *testing.T) { timeNow: tt.timeNow, userFinder: userFinder, } - err := s.FindByUIN(nil, tt.sess, tt.req, tt.seq) + err := s.FindByInterests(nil, tt.sess, tt.req, tt.seq) assert.NoError(t, err) }) } } -func TestICQService_FindByWhitePages(t *testing.T) { +func TestICQService_FindByWhitePages2(t *testing.T) { tests := []struct { name string timeNow func() time.Time seq uint16 sess *state.Session - req wire.ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages + req wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2 mockParams mockParams wantErr error }{ { - name: "happy path", + name: "search by keyword", timeNow: func() time.Time { return time.Date(2020, time.August, 1, 0, 0, 0, 0, time.UTC) }, seq: 1, sess: newTestSession("11111111", sessOptUIN(11111111)), - req: wire.ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages{ - InterestsCode: 10, - InterestsKeyword: "knitting,crocheting,sewing", + req: wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVLE(wire.ICQTLVTagsWhitepagesSearchKeywords, struct { + Val string `oscar:"len_prefix=uint16,nullterm"` + }{ + Val: "knitting", + }), + }, + }, }, mockParams: mockParams{ icqUserFinderParams: icqUserFinderParams{ - findByInterestsParams: findByInterestsParams{ + findByKeywordParams: findByKeywordParams{ { - code: 10, - keywords: []string{"knitting", "crocheting", "sewing"}, + keyword: "knitting", result: []state.User{ { IdentScreenName: state.NewIdentScreenName("987654321"), @@ -605,7 +1092,7 @@ func TestICQService_FindByWhitePages(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -642,7 +1129,7 @@ func TestICQService_FindByWhitePages(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -690,13 +1177,132 @@ func TestICQService_FindByWhitePages(t *testing.T) { }, }, }, + { + name: "search by name", + timeNow: func() time.Time { + return time.Date(2020, time.August, 1, 0, 0, 0, 0, time.UTC) + }, + seq: 1, + sess: newTestSession("11111111", sessOptUIN(11111111)), + req: wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVLE(wire.ICQTLVTagsNickname, struct { + Val string `oscar:"len_prefix=uint16,nullterm"` + }{ + Val: "Janey", + }), + wire.NewTLVLE(wire.ICQTLVTagsFirstName, struct { + Val string `oscar:"len_prefix=uint16,nullterm"` + }{ + Val: "Jane", + }), + wire.NewTLVLE(wire.ICQTLVTagsLastName, struct { + Val string `oscar:"len_prefix=uint16,nullterm"` + }{ + Val: "Janey", + }), + }, + }, + }, + mockParams: mockParams{ + icqUserFinderParams: icqUserFinderParams{ + findByDetailsParams: findByDetailsParams{ + { + nickName: "Janey", + firstName: "Jane", + lastName: "Janey", + result: []state.User{ + { + IdentScreenName: state.NewIdentScreenName("987654321"), + ICQBasicInfo: state.ICQBasicInfo{ + EmailAddress: "janey@example.com", + FirstName: "Jane", + LastName: "Doe", + Nickname: "Janey", + }, + ICQPermissions: state.ICQPermissions{ + AuthRequired: false, + }, + ICQMoreInfo: state.ICQMoreInfo{ + BirthDay: 31, + BirthMonth: 7, + BirthYear: 1995, + Gender: 2, + }, + }, + }, + }, + }, + }, + messageRelayerParams: messageRelayerParams{ + relayToScreenNameParams: relayToScreenNameParams{ + { + screenName: state.NewIdentScreenName("11111111"), + message: wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.ICQ, + SubGroup: wire.ICQDBReply, + }, + Body: wire.SNAC_0x15_0x02_DBReply{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + Message: wire.ICQ_0x07DA_0x01AE_DBQueryMetaReplyLastUserFound{ + ICQMetadata: wire.ICQMetadata{ + UIN: 11111111, + ReqType: wire.ICQDBQueryMetaReply, + Seq: 1, + }, + Success: wire.ICQStatusCodeOK, + ReqSubType: wire.ICQDBQueryMetaReplyLastUserFound, + Details: wire.ICQUserSearchRecord{ + UIN: 987654321, + Nickname: "Janey", + FirstName: "Jane", + LastName: "Doe", + Email: "janey@example.com", + Authorization: 0, + OnlineStatus: 0, + Gender: 2, + Age: 25, + }, + LastMessageFooter: &struct { + FoundUsersLeft uint32 + }{ + FoundUsersLeft: 0, + }, + }, + }), + }, + }, + }, + }, + }, + }, + }, + sessionRetrieverParams: sessionRetrieverParams{ + retrieveSessionParams{ + { + screenName: state.NewIdentScreenName("987654321"), + result: nil, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { userFinder := newMockICQUserFinder(t) - for _, params := range tt.mockParams.findByInterestsParams { + for _, params := range tt.mockParams.findByKeywordParams { userFinder.EXPECT(). - FindByInterests(params.code, params.keywords). + FindByKeyword(params.keyword). + Return(params.result, params.err) + } + for _, params := range tt.mockParams.findByDetailsParams { + userFinder.EXPECT(). + FindByDetails(params.firstName, params.lastName, params.nickName). Return(params.result, params.err) } @@ -718,7 +1324,7 @@ func TestICQService_FindByWhitePages(t *testing.T) { timeNow: tt.timeNow, userFinder: userFinder, } - err := s.FindByInterests(nil, tt.sess, tt.req, tt.seq) + err := s.FindByWhitePages2(nil, tt.sess, tt.req, tt.seq) assert.NoError(t, err) }) } @@ -837,7 +1443,7 @@ func TestICQService_FullUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00C8_DBQueryMetaReplyBasicInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -881,7 +1487,7 @@ func TestICQService_FullUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -922,7 +1528,7 @@ func TestICQService_FullUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00EB_DBQueryMetaReplyExtEmailInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -948,7 +1554,7 @@ func TestICQService_FullUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x010E_DBQueryMetaReplyHomePageCat{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -974,7 +1580,7 @@ func TestICQService_FullUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00D2_DBQueryMetaReplyWorkInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -1014,7 +1620,7 @@ func TestICQService_FullUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00E6_DBQueryMetaReplyNotes{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -1043,7 +1649,7 @@ func TestICQService_FullUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00F0_DBQueryMetaReplyInterests{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -1090,7 +1696,7 @@ func TestICQService_FullUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00FA_DBQueryMetaReplyAffiliations{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -1205,7 +1811,7 @@ func TestICQService_OfflineMsgReq(t *testing.T) { ChannelID: wire.ICBMChannelIM, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICBMTLVAOLIMData, func() []wire.ICBMCh1Fragment { + wire.NewTLVBE(wire.ICBMTLVAOLIMData, func() []wire.ICBMCh1Fragment { frags, err := wire.ICBMFragmentList("hello!") assert.NoError(t, err) return frags @@ -1222,7 +1828,7 @@ func TestICQService_OfflineMsgReq(t *testing.T) { ChannelID: wire.ICBMChannelICQ, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICBMTLVData, func() []byte { + wire.NewTLVBE(wire.ICBMTLVData, func() []byte { msg := wire.ICBMCh4Message{ UIN: 33333333, MessageType: wire.ICBMExtendedMsgTypeAuthReq, @@ -1254,7 +1860,7 @@ func TestICQService_OfflineMsgReq(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x0041_DBQueryOfflineMsgReply{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -1286,7 +1892,7 @@ func TestICQService_OfflineMsgReq(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x0041_DBQueryOfflineMsgReply{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -1318,7 +1924,7 @@ func TestICQService_OfflineMsgReq(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x0042_DBQueryOfflineMsgReplyLast{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -1441,7 +2047,7 @@ func TestICQService_SetAffiliations(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 100003, @@ -1549,7 +2155,7 @@ func TestICQService_SetEmails(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 100003, @@ -1652,7 +2258,7 @@ func TestICQService_SetBasicInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 100003, @@ -1763,7 +2369,7 @@ func TestICQService_SetInterests(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 100003, @@ -1883,7 +2489,7 @@ func TestICQService_SetMoreInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 100003, @@ -1955,7 +2561,7 @@ func TestICQService_SetPermissions(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 100003, @@ -2032,7 +2638,7 @@ func TestICQService_SetUserNotes(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 100003, @@ -2138,7 +2744,7 @@ func TestICQService_SetWorkInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x00DC_DBQueryMetaReplyMoreInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 100003, @@ -2238,7 +2844,7 @@ func TestICQService_ShortUserInfo(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x0104_DBQueryMetaReplyShortInfo{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, @@ -2331,7 +2937,7 @@ func TestICQService_XMLReqData(t *testing.T) { Body: wire.SNAC_0x15_0x02_DBReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQ_0x07DA_0x08A2_DBQueryMetaReplyXMLData{ ICQMetadata: wire.ICQMetadata{ UIN: 11111111, diff --git a/foodgroup/locate.go b/foodgroup/locate.go index 51188b21..020151e6 100644 --- a/foodgroup/locate.go +++ b/foodgroup/locate.go @@ -58,11 +58,11 @@ func (s LocateService) RightsQuery(_ context.Context, inFrame wire.SNACFrame) wi TLVList: wire.TLVList{ // these are arbitrary values--AIM clients seem to perform // OK with them - wire.NewTLV(wire.LocateTLVTagsRightsMaxSigLen, uint16(1000)), - wire.NewTLV(wire.LocateTLVTagsRightsMaxCapabilitiesLen, uint16(1000)), - wire.NewTLV(wire.LocateTLVTagsRightsMaxFindByEmailList, uint16(1000)), - wire.NewTLV(wire.LocateTLVTagsRightsMaxCertsLen, uint16(1000)), - wire.NewTLV(wire.LocateTLVTagsRightsMaxMaxShortCapabilities, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxSigLen, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxCapabilitiesLen, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxFindByEmailList, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxCertsLen, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxMaxShortCapabilities, uint16(1000)), }, }, }, @@ -87,7 +87,7 @@ func (s LocateService) SetInfo(ctx context.Context, sess *state.Session, inBody } // update client capabilities (buddy icon, chat, etc...) - if b, hasCaps := inBody.Slice(wire.LocateTLVTagsInfoCapabilities); hasCaps { + if b, hasCaps := inBody.Bytes(wire.LocateTLVTagsInfoCapabilities); hasCaps { if len(b)%16 != 0 { return errors.New("capability list must be array of 16-byte values") } @@ -152,15 +152,15 @@ func (s LocateService) UserInfoQuery(_ context.Context, sess *state.Session, inF return wire.SNACMessage{}, err } list.AppendList([]wire.TLV{ - wire.NewTLV(wire.LocateTLVTagsInfoSigMime, `text/aolrtf; charset="us-ascii"`), - wire.NewTLV(wire.LocateTLVTagsInfoSigData, profile), + wire.NewTLVBE(wire.LocateTLVTagsInfoSigMime, `text/aolrtf; charset="us-ascii"`), + wire.NewTLVBE(wire.LocateTLVTagsInfoSigData, profile), }) } if inBody.RequestAwayMessage() { list.AppendList([]wire.TLV{ - wire.NewTLV(wire.LocateTLVTagsInfoUnavailableMime, `text/aolrtf; charset="us-ascii"`), - wire.NewTLV(wire.LocateTLVTagsInfoUnavailableData, buddySess.AwayMessage()), + wire.NewTLVBE(wire.LocateTLVTagsInfoUnavailableMime, `text/aolrtf; charset="us-ascii"`), + wire.NewTLVBE(wire.LocateTLVTagsInfoUnavailableData, buddySess.AwayMessage()), }) } diff --git a/foodgroup/locate_test.go b/foodgroup/locate_test.go index 8a59588d..6790f07a 100644 --- a/foodgroup/locate_test.go +++ b/foodgroup/locate_test.go @@ -128,8 +128,8 @@ func TestLocateService_UserInfoQuery(t *testing.T) { TLVUserInfo(), LocateInfo: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LocateTLVTagsInfoSigMime, `text/aolrtf; charset="us-ascii"`), - wire.NewTLV(wire.LocateTLVTagsInfoSigData, "this is my profile!"), + wire.NewTLVBE(wire.LocateTLVTagsInfoSigMime, `text/aolrtf; charset="us-ascii"`), + wire.NewTLVBE(wire.LocateTLVTagsInfoSigData, "this is my profile!"), }, }, }, @@ -190,8 +190,8 @@ func TestLocateService_UserInfoQuery(t *testing.T) { TLVUserInfo(), LocateInfo: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LocateTLVTagsInfoSigMime, `text/aolrtf; charset="us-ascii"`), - wire.NewTLV(wire.LocateTLVTagsInfoSigData, "this is my profile!"), + wire.NewTLVBE(wire.LocateTLVTagsInfoSigMime, `text/aolrtf; charset="us-ascii"`), + wire.NewTLVBE(wire.LocateTLVTagsInfoSigData, "this is my profile!"), }, }, }, @@ -244,8 +244,8 @@ func TestLocateService_UserInfoQuery(t *testing.T) { TLVUserInfo(), LocateInfo: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LocateTLVTagsInfoUnavailableMime, `text/aolrtf; charset="us-ascii"`), - wire.NewTLV(wire.LocateTLVTagsInfoUnavailableData, "this is my away message!"), + wire.NewTLVBE(wire.LocateTLVTagsInfoUnavailableMime, `text/aolrtf; charset="us-ascii"`), + wire.NewTLVBE(wire.LocateTLVTagsInfoUnavailableData, "this is my away message!"), }, }, }, @@ -417,7 +417,7 @@ func TestLocateService_SetInfo(t *testing.T) { inBody: wire.SNAC_0x02_0x04_LocateSetInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LocateTLVTagsInfoSigData, "profile-result"), + wire.NewTLVBE(wire.LocateTLVTagsInfoSigData, "profile-result"), }, }, }, @@ -438,7 +438,7 @@ func TestLocateService_SetInfo(t *testing.T) { inBody: wire.SNAC_0x02_0x04_LocateSetInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LocateTLVTagsInfoUnavailableData, "this is my away message!"), + wire.NewTLVBE(wire.LocateTLVTagsInfoUnavailableData, "this is my away message!"), }, }, }, @@ -484,7 +484,7 @@ func TestLocateService_SetInfo_SetCaps(t *testing.T) { inBody := wire.SNAC_0x02_0x04_LocateSetInfo{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LocateTLVTagsInfoCapabilities, []byte{ + wire.NewTLVBE(wire.LocateTLVTagsInfoCapabilities, []byte{ // chat: "748F2420-6287-11D1-8222-444553540000" 0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00, // avatar: "09461346-4c7f-11d1-8222-444553540000" @@ -523,11 +523,11 @@ func TestLocateService_RightsQuery(t *testing.T) { Body: wire.SNAC_0x02_0x03_LocateRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.LocateTLVTagsRightsMaxSigLen, uint16(1000)), - wire.NewTLV(wire.LocateTLVTagsRightsMaxCapabilitiesLen, uint16(1000)), - wire.NewTLV(wire.LocateTLVTagsRightsMaxFindByEmailList, uint16(1000)), - wire.NewTLV(wire.LocateTLVTagsRightsMaxCertsLen, uint16(1000)), - wire.NewTLV(wire.LocateTLVTagsRightsMaxMaxShortCapabilities, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxSigLen, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxCapabilitiesLen, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxFindByEmailList, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxCertsLen, uint16(1000)), + wire.NewTLVBE(wire.LocateTLVTagsRightsMaxMaxShortCapabilities, uint16(1000)), }, }, }, diff --git a/foodgroup/mock_icq_user_finder_test.go b/foodgroup/mock_icq_user_finder_test.go index a637e57a..bc6cf7f4 100644 --- a/foodgroup/mock_icq_user_finder_test.go +++ b/foodgroup/mock_icq_user_finder_test.go @@ -195,6 +195,64 @@ func (_c *mockICQUserFinder_FindByInterests_Call) RunAndReturn(run func(uint16, return _c } +// FindByKeyword provides a mock function with given fields: keyword +func (_m *mockICQUserFinder) FindByKeyword(keyword string) ([]state.User, error) { + ret := _m.Called(keyword) + + if len(ret) == 0 { + panic("no return value specified for FindByKeyword") + } + + var r0 []state.User + var r1 error + if rf, ok := ret.Get(0).(func(string) ([]state.User, error)); ok { + return rf(keyword) + } + if rf, ok := ret.Get(0).(func(string) []state.User); ok { + r0 = rf(keyword) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]state.User) + } + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(keyword) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// mockICQUserFinder_FindByKeyword_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindByKeyword' +type mockICQUserFinder_FindByKeyword_Call struct { + *mock.Call +} + +// FindByKeyword is a helper method to define mock.On call +// - keyword string +func (_e *mockICQUserFinder_Expecter) FindByKeyword(keyword interface{}) *mockICQUserFinder_FindByKeyword_Call { + return &mockICQUserFinder_FindByKeyword_Call{Call: _e.mock.On("FindByKeyword", keyword)} +} + +func (_c *mockICQUserFinder_FindByKeyword_Call) Run(run func(keyword string)) *mockICQUserFinder_FindByKeyword_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *mockICQUserFinder_FindByKeyword_Call) Return(_a0 []state.User, _a1 error) *mockICQUserFinder_FindByKeyword_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *mockICQUserFinder_FindByKeyword_Call) RunAndReturn(run func(string) ([]state.User, error)) *mockICQUserFinder_FindByKeyword_Call { + _c.Call.Return(run) + return _c +} + // FindByUIN provides a mock function with given fields: UIN func (_m *mockICQUserFinder) FindByUIN(UIN uint32) (state.User, error) { ret := _m.Called(UIN) diff --git a/foodgroup/oservice.go b/foodgroup/oservice.go index 09d85789..77173fba 100644 --- a/foodgroup/oservice.go +++ b/foodgroup/oservice.go @@ -424,7 +424,7 @@ func (s OServiceService) UserInfoQuery(_ context.Context, sess *state.Session, i // to 0x0100, set invisible. Else, return an error for any other value. // It returns SNAC wire.OServiceUserInfoUpdate containing the user's info. func (s OServiceService) SetUserInfoFields(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, inBody wire.SNAC_0x01_0x1E_OServiceSetUserInfoFields) (wire.SNACMessage, error) { - if status, hasStatus := inBody.Uint32(wire.OServiceUserInfoStatus); hasStatus { + if status, hasStatus := inBody.Uint32BE(wire.OServiceUserInfoStatus); hasStatus { sess.SetUserStatusBitmask(status) if sess.Invisible() { if err := s.buddyUpdateBroadcaster.BroadcastBuddyDeparted(ctx, sess); err != nil { @@ -598,11 +598,11 @@ func (s OServiceServiceForBOS) ServiceRequest(ctx context.Context, sess *state.S Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.AdminPort)), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, cookie), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.Admin), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.AdminPort)), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, cookie), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.Admin), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, @@ -623,11 +623,11 @@ func (s OServiceServiceForBOS) ServiceRequest(ctx context.Context, sess *state.S Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.AlertPort)), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, cookie), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.Alert), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.AlertPort)), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, cookie), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.Alert), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, @@ -648,11 +648,11 @@ func (s OServiceServiceForBOS) ServiceRequest(ctx context.Context, sess *state.S Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.BARTPort)), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, cookie), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.BART), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.BARTPort)), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, cookie), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.BART), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, @@ -673,17 +673,17 @@ func (s OServiceServiceForBOS) ServiceRequest(ctx context.Context, sess *state.S Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.ChatNavPort)), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, cookie), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.ChatNav), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.ChatNavPort)), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, cookie), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.ChatNav), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, }, nil case wire.Chat: - roomMeta, ok := inBody.Slice(0x01) + roomMeta, ok := inBody.Bytes(0x01) if !ok { return wire.SNACMessage{}, errors.New("missing room info") } @@ -715,11 +715,11 @@ func (s OServiceServiceForBOS) ServiceRequest(ctx context.Context, sess *state.S Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.ChatPort)), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, cookie), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.Chat), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, net.JoinHostPort(s.cfg.OSCARHost, s.cfg.ChatPort)), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, cookie), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.Chat), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, diff --git a/foodgroup/oservice_test.go b/foodgroup/oservice_test.go index b9c1d618..6670f574 100644 --- a/foodgroup/oservice_test.go +++ b/foodgroup/oservice_test.go @@ -84,11 +84,11 @@ func TestOServiceServiceForBOS_ServiceRequest(t *testing.T) { Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, []byte("the-cookie")), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.ChatNav), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.ChatNav), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, @@ -130,11 +130,11 @@ func TestOServiceServiceForBOS_ServiceRequest(t *testing.T) { Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, []byte("the-cookie")), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.Alert), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.Alert), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, @@ -176,11 +176,11 @@ func TestOServiceServiceForBOS_ServiceRequest(t *testing.T) { Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, []byte("the-cookie")), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.Admin), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, []byte("the-cookie")), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.Admin), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, @@ -213,7 +213,7 @@ func TestOServiceServiceForBOS_ServiceRequest(t *testing.T) { FoodGroup: wire.Chat, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, wire.SNAC_0x01_0x04_TLVRoomInfo{ + wire.NewTLVBE(0x01, wire.SNAC_0x01_0x04_TLVRoomInfo{ Exchange: chatRoom.Exchange(), Cookie: chatRoom.Cookie(), InstanceNumber: chatRoom.InstanceNumber(), @@ -231,11 +231,11 @@ func TestOServiceServiceForBOS_ServiceRequest(t *testing.T) { Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceTLVTagsReconnectHere, "127.0.0.1:1234"), - wire.NewTLV(wire.OServiceTLVTagsLoginCookie, []byte("the-auth-cookie")), - wire.NewTLV(wire.OServiceTLVTagsGroupID, wire.Chat), - wire.NewTLV(wire.OServiceTLVTagsSSLCertName, ""), - wire.NewTLV(wire.OServiceTLVTagsSSLState, uint8(0x00)), + wire.NewTLVBE(wire.OServiceTLVTagsReconnectHere, "127.0.0.1:1234"), + wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, []byte("the-auth-cookie")), + wire.NewTLVBE(wire.OServiceTLVTagsGroupID, wire.Chat), + wire.NewTLVBE(wire.OServiceTLVTagsSSLCertName, ""), + wire.NewTLVBE(wire.OServiceTLVTagsSSLState, uint8(0x00)), }, }, }, @@ -279,7 +279,7 @@ func TestOServiceServiceForBOS_ServiceRequest(t *testing.T) { FoodGroup: wire.Chat, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, wire.SNAC_0x01_0x04_TLVRoomInfo{ + wire.NewTLVBE(0x01, wire.SNAC_0x01_0x04_TLVRoomInfo{ Exchange: 8, Cookie: "the-chat-cookie", InstanceNumber: 16, @@ -373,7 +373,7 @@ func TestSetUserInfoFields(t *testing.T) { Body: wire.SNAC_0x01_0x1E_OServiceSetUserInfoFields{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0000)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)), }, }, }, @@ -408,7 +408,7 @@ func TestSetUserInfoFields(t *testing.T) { Body: wire.SNAC_0x01_0x1E_OServiceSetUserInfoFields{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0100)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0100)), }, }, }, diff --git a/foodgroup/permit_deny.go b/foodgroup/permit_deny.go index 424b7d67..fbe58a60 100644 --- a/foodgroup/permit_deny.go +++ b/foodgroup/permit_deny.go @@ -32,9 +32,9 @@ func (s PermitDenyService) RightsQuery(_ context.Context, frame wire.SNACFrame) Body: wire.SNAC_0x09_0x03_PermitDenyRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.PermitDenyTLVMaxDenies, uint16(100)), - wire.NewTLV(wire.PermitDenyTLVMaxPermits, uint16(100)), - wire.NewTLV(wire.PermitDenyTLVMaxTempPermits, uint16(100)), + wire.NewTLVBE(wire.PermitDenyTLVMaxDenies, uint16(100)), + wire.NewTLVBE(wire.PermitDenyTLVMaxPermits, uint16(100)), + wire.NewTLVBE(wire.PermitDenyTLVMaxTempPermits, uint16(100)), }, }, }, diff --git a/foodgroup/permit_deny_test.go b/foodgroup/permit_deny_test.go index 0fc41874..658fac23 100644 --- a/foodgroup/permit_deny_test.go +++ b/foodgroup/permit_deny_test.go @@ -21,9 +21,9 @@ func TestPermitDenyService_RightsQuery(t *testing.T) { Body: wire.SNAC_0x09_0x03_PermitDenyRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.PermitDenyTLVMaxDenies, uint16(100)), - wire.NewTLV(wire.PermitDenyTLVMaxPermits, uint16(100)), - wire.NewTLV(wire.PermitDenyTLVMaxTempPermits, uint16(100)), + wire.NewTLVBE(wire.PermitDenyTLVMaxDenies, uint16(100)), + wire.NewTLVBE(wire.PermitDenyTLVMaxPermits, uint16(100)), + wire.NewTLVBE(wire.PermitDenyTLVMaxTempPermits, uint16(100)), }, }, }, diff --git a/foodgroup/test_helpers.go b/foodgroup/test_helpers.go index 495c681b..8d481046 100644 --- a/foodgroup/test_helpers.go +++ b/foodgroup/test_helpers.go @@ -77,10 +77,19 @@ type retrieveSessionParams []struct { // icqUserFinderParams is a helper struct that contains mock parameters for // ICQUserFinder methods type icqUserFinderParams struct { - findByUINParams - findByEmailParams findByDetailsParams + findByEmailParams findByInterestsParams + findByKeywordParams + findByUINParams +} + +// findByKeywordParams is the list of parameters passed at the mock +// ICQUserFinder.FindByKeyword call site +type findByKeywordParams []struct { + keyword string + result []state.User + err error } // findByUINParams is the list of parameters passed at the mock @@ -345,7 +354,6 @@ type relayToScreenNamesParams []struct { // relayToScreenNameParams is the list of parameters passed at the mock // MessageRelayer.RelayToScreenName call site type relayToScreenNameParams []struct { - cookie string screenName state.IdentScreenName message wire.SNACMessage } @@ -690,7 +698,7 @@ func newTestSession(screenName state.DisplayScreenName, options ...func(session func userInfoWithBARTIcon(sess *state.Session, bid wire.BARTID) wire.TLVUserInfo { info := sess.TLVUserInfo() - info.Append(wire.NewTLV(wire.OServiceUserInfoBARTInfo, bid)) + info.Append(wire.NewTLVBE(wire.OServiceUserInfoBARTInfo, bid)) return info } diff --git a/foodgroup/types.go b/foodgroup/types.go index 04df6d34..a9273564 100644 --- a/foodgroup/types.go +++ b/foodgroup/types.go @@ -175,14 +175,20 @@ type AccountManager interface { } type ICQUserFinder interface { - // FindByUIN returns a user where the UIN matches the ident screen name. + // FindByUIN returns a user with a matching UIN. FindByUIN(UIN uint32) (state.User, error) // FindByEmail returns a user with a matching email address. FindByEmail(email string) (state.User, error) - // FindByDetails returns a user with either a matching first name, last name, or nickname. + // FindByDetails returns users with either a matching first name, last + // name, and nickname. Empty values are not included in the search + // parameters. FindByDetails(firstName, lastName, nickName string) ([]state.User, error) - // FindByInterests returns a user who has at least one matching interest. + // FindByInterests returns users who have at least one matching interest + // for a given category code. FindByInterests(code uint16, keywords []string) ([]state.User, error) + // FindByKeyword returns users with matching interest keyword across all + // interest categories. + FindByKeyword(keyword string) ([]state.User, error) } type ICQUserUpdater interface { diff --git a/server/http/mgmt_api.go b/server/http/mgmt_api.go index 8a61c8dc..d72399ec 100644 --- a/server/http/mgmt_api.go +++ b/server/http/mgmt_api.go @@ -473,7 +473,7 @@ func postInstantMessageHandler(w http.ResponseWriter, r *http.Request, messageRe }, TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICBMTLVAOLIMData, tlv), + wire.NewTLVBE(wire.ICBMTLVAOLIMData, tlv), }, }, }, diff --git a/server/http/mgmt_api_test.go b/server/http/mgmt_api_test.go index 24a4dd66..5425f78a 100644 --- a/server/http/mgmt_api_test.go +++ b/server/http/mgmt_api_test.go @@ -1315,7 +1315,7 @@ func TestInstantMessageHandler_POST(t *testing.T) { body := msg.Body.(wire.SNAC_0x04_0x07_ICBMChannelMsgToClient) assert.Equal(t, params.sender.String(), body.TLVUserInfo.ScreenName) - b, ok := body.Slice(wire.ICBMTLVAOLIMData) + b, ok := body.Bytes(wire.ICBMTLVAOLIMData) assert.True(t, ok) txt, err := wire.UnmarshalICBMMessageText(b) diff --git a/server/oscar/admin.go b/server/oscar/admin.go index 6194815e..9de702c8 100644 --- a/server/oscar/admin.go +++ b/server/oscar/admin.go @@ -68,7 +68,7 @@ func (rt AdminServer) handleNewConnection(ctx context.Context, rwc io.ReadWriteC return err } - authCookie, ok := flap.Slice(wire.OServiceTLVTagsLoginCookie) + authCookie, ok := flap.Bytes(wire.OServiceTLVTagsLoginCookie) if !ok { return errors.New("unable to get session id from payload") } diff --git a/server/oscar/auth.go b/server/oscar/auth.go index a77c987e..5f045a5b 100644 --- a/server/oscar/auth.go +++ b/server/oscar/auth.go @@ -77,7 +77,7 @@ func (rt AuthServer) handleNewConnection(rwc io.ReadWriteCloser) error { // presence of the roasted password TLV, however that proved an unreliable // indicator of FLAP-auth because older ICQ clients appear to omit the // roasted password TLV when the password is not stored client-side. - if _, hasScreenName := signonFrame.Uint16(wire.LoginTLVTagsScreenName); hasScreenName { + if _, hasScreenName := signonFrame.Uint16BE(wire.LoginTLVTagsScreenName); hasScreenName { return rt.processFLAPAuth(signonFrame, flapc) } diff --git a/server/oscar/bos.go b/server/oscar/bos.go index 6c0b5d70..0103b760 100644 --- a/server/oscar/bos.go +++ b/server/oscar/bos.go @@ -71,7 +71,7 @@ func (rt BOSServer) handleNewConnection(ctx context.Context, rwc io.ReadWriteClo return err } - authCookie, ok := flap.Slice(wire.OServiceTLVTagsLoginCookie) + authCookie, ok := flap.Bytes(wire.OServiceTLVTagsLoginCookie) if !ok { return errors.New("unable to get session id from payload") } diff --git a/server/oscar/bos_test.go b/server/oscar/bos_test.go index f4e8fed9..0cae12d3 100644 --- a/server/oscar/bos_test.go +++ b/server/oscar/bos_test.go @@ -45,7 +45,7 @@ func TestBOSService_handleNewConnection(t *testing.T) { flapSignonFrame = wire.FLAPSignonFrame{ FLAPVersion: 1, } - flapSignonFrame.Append(wire.NewTLV(wire.OServiceTLVTagsLoginCookie, []byte("the-cookie"))) + flapSignonFrame.Append(wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, []byte("the-cookie"))) buf := &bytes.Buffer{} assert.NoError(t, wire.MarshalBE(flapSignonFrame, buf)) flap = wire.FLAPFrame{ diff --git a/server/oscar/chat.go b/server/oscar/chat.go index 1ed59803..d7a99a90 100644 --- a/server/oscar/chat.go +++ b/server/oscar/chat.go @@ -62,7 +62,7 @@ func (rt ChatServer) handleNewConnection(ctx context.Context, rwc io.ReadWriteCl return err } - authCookie, ok := flap.Slice(wire.OServiceTLVTagsLoginCookie) + authCookie, ok := flap.Bytes(wire.OServiceTLVTagsLoginCookie) if !ok { return errors.New("unable to get login cookie from payload") } diff --git a/server/oscar/chat_test.go b/server/oscar/chat_test.go index 719b37f9..b88591b3 100644 --- a/server/oscar/chat_test.go +++ b/server/oscar/chat_test.go @@ -31,7 +31,7 @@ func TestChatService_handleNewConnection(t *testing.T) { flapSignonFrame = wire.FLAPSignonFrame{ FLAPVersion: 1, } - flapSignonFrame.Append(wire.NewTLV(wire.OServiceTLVTagsLoginCookie, []byte(`the-chat-login-cookie`))) + flapSignonFrame.Append(wire.NewTLVBE(wire.OServiceTLVTagsLoginCookie, []byte(`the-chat-login-cookie`))) buf := &bytes.Buffer{} assert.NoError(t, wire.MarshalBE(flapSignonFrame, buf)) flap = wire.FLAPFrame{ diff --git a/server/oscar/handler/admin_test.go b/server/oscar/handler/admin_test.go index 2fb69bd5..7bae0266 100644 --- a/server/oscar/handler/admin_test.go +++ b/server/oscar/handler/admin_test.go @@ -56,7 +56,7 @@ func TestAdminHandler_InfoQuery_RegistrationStatus(t *testing.T) { Body: wire.SNAC_0x07_0x02_AdminInfoQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVRegistrationStatus, uint16(0x00))}, + wire.NewTLVBE(wire.AdminTLVRegistrationStatus, uint16(0x00))}, }, }, } @@ -69,7 +69,7 @@ func TestAdminHandler_InfoQuery_RegistrationStatus(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusFullDisclosure), + wire.NewTLVBE(wire.AdminTLVRegistrationStatus, wire.AdminInfoRegStatusFullDisclosure), }, }, }, @@ -102,7 +102,7 @@ func TestAdminHandler_InfoChangeRequest_ScreenNameFormatted(t *testing.T) { Body: wire.SNAC_0x07_0x04_AdminInfoChangeRequest{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, "Chatting Chuck")}, + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck")}, }, }, } @@ -115,7 +115,7 @@ func TestAdminHandler_InfoChangeRequest_ScreenNameFormatted(t *testing.T) { Permissions: wire.AdminInfoPermissionsReadWrite, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"), + wire.NewTLVBE(wire.AdminTLVScreenNameFormatted, "Chatting Chuck"), }, }, }, diff --git a/server/oscar/handler/buddy_test.go b/server/oscar/handler/buddy_test.go index d9e5d3f7..9b4bd10a 100644 --- a/server/oscar/handler/buddy_test.go +++ b/server/oscar/handler/buddy_test.go @@ -20,7 +20,7 @@ func TestBuddyHandler_RightsQuery(t *testing.T) { Body: wire.SNAC_0x03_0x02_BuddyRightsQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, uint16(1000)), + wire.NewTLVBE(0x01, uint16(1000)), }, }, }, @@ -33,7 +33,7 @@ func TestBuddyHandler_RightsQuery(t *testing.T) { Body: wire.SNAC_0x03_0x03_BuddyRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, uint16(1000)), + wire.NewTLVBE(0x01, uint16(1000)), }, }, }, diff --git a/server/oscar/handler/feedbag.go b/server/oscar/handler/feedbag.go index d3bf128e..1eb88577 100644 --- a/server/oscar/handler/feedbag.go +++ b/server/oscar/handler/feedbag.go @@ -16,6 +16,7 @@ type FeedbagService interface { DeleteItem(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, inBody wire.SNAC_0x13_0x0A_FeedbagDeleteItem) (wire.SNACMessage, error) Query(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame) (wire.SNACMessage, error) QueryIfModified(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, inBody wire.SNAC_0x13_0x05_FeedbagQueryIfModified) (wire.SNACMessage, error) + RespondAuthorizeToHost(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, inBody wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost) error RightsQuery(ctx context.Context, inFrame wire.SNACFrame) wire.SNACMessage StartCluster(ctx context.Context, inFrame wire.SNACFrame, inBody wire.SNAC_0x13_0x11_FeedbagStartCluster) UpsertItem(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, items []wire.FeedbagItem) (wire.SNACMessage, error) @@ -126,3 +127,15 @@ func (h FeedbagHandler) EndCluster(ctx context.Context, _ *state.Session, inFram h.LogRequest(ctx, inFrame, nil) return nil } + +func (h FeedbagHandler) RespondAuthorizeToHost(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, r io.Reader, rw oscar.ResponseWriter) error { + inBody := wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost{} + if err := wire.UnmarshalBE(&inBody, r); err != nil { + return err + } + if err := h.FeedbagService.RespondAuthorizeToHost(ctx, sess, inFrame, inBody); err != nil { + return err + } + h.LogRequest(ctx, inFrame, inBody) + return nil +} diff --git a/server/oscar/handler/feedbag_test.go b/server/oscar/handler/feedbag_test.go index fd30ed14..05ae9c57 100644 --- a/server/oscar/handler/feedbag_test.go +++ b/server/oscar/handler/feedbag_test.go @@ -345,3 +345,28 @@ func TestFeedbagHandler_Use(t *testing.T) { assert.NoError(t, h.Use(nil, nil, input.Frame, buf, responseWriter)) } + +func TestFeedbagHandler_RespondAuthorizeToHost(t *testing.T) { + input := wire.SNACMessage{ + Frame: wire.SNACFrame{ + FoodGroup: wire.Feedbag, + SubGroup: wire.FeedbagRequestAuthorizeToHost, + }, + Body: wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost{ + ScreenName: "theScreenName", + }, + } + + svc := newMockFeedbagService(t) + svc.EXPECT(). + RespondAuthorizeToHost(mock.Anything, mock.Anything, input.Frame, input.Body). + Return(nil) + + h := NewFeedbagHandler(slog.Default(), svc) + responseWriter := newMockResponseWriter(t) + + buf := &bytes.Buffer{} + assert.NoError(t, wire.MarshalBE(input.Body, buf)) + + assert.NoError(t, h.RespondAuthorizeToHost(nil, nil, input.Frame, buf, responseWriter)) +} diff --git a/server/oscar/handler/icq.go b/server/oscar/handler/icq.go index f7051133..92756830 100644 --- a/server/oscar/handler/icq.go +++ b/server/oscar/handler/icq.go @@ -19,8 +19,11 @@ type ICQService interface { DeleteMsgReq(ctx context.Context, sess *state.Session, seq uint16) error FindByDetails(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0515_DBQueryMetaReqSearchByDetails, seq uint16) error FindByEmail(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0529_DBQueryMetaReqSearchByEmail, seq uint16) error + FindByEmail3(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3, seq uint16) error FindByInterests(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages, seq uint16) error FindByUIN(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN, seq uint16) error + FindByUIN2(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2, seq uint16) error + FindByWhitePages2(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2, seq uint16) error FullUserInfo(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN, seq uint16) error OfflineMsgReq(ctx context.Context, sess *state.Session, seq uint16) error SetAffiliations(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x041A_DBQueryMetaReqSetAffiliations, seq uint16) error @@ -60,7 +63,7 @@ func (rt ICQHandler) DBQuery(ctx context.Context, sess *state.Session, inFrame w return err } - md, ok := inBody.Slice(wire.ICQTLVTagsMetadata) + md, ok := inBody.Bytes(wire.ICQTLVTagsMetadata) if !ok { return errors.New("invalid ICQ frame") } @@ -126,6 +129,14 @@ func (rt ICQHandler) DBQuery(ctx context.Context, sess *state.Session, inFrame w if err := rt.ICQService.FindByUIN(ctx, sess, req, icqMD.Seq); err != nil { return err } + case wire.ICQDBQueryMetaReqSearchByUIN2: + req := wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2{} + if err := wire.UnmarshalLE(&req, buf); err != nil { + return err + } + if err := rt.ICQService.FindByUIN2(ctx, sess, req, icqMD.Seq); err != nil { + return err + } case wire.ICQDBQueryMetaReqSearchByEmail: req := wire.ICQ_0x07D0_0x0529_DBQueryMetaReqSearchByEmail{} if err := wire.UnmarshalLE(&req, buf); err != nil { @@ -134,6 +145,14 @@ func (rt ICQHandler) DBQuery(ctx context.Context, sess *state.Session, inFrame w if err := rt.ICQService.FindByEmail(ctx, sess, req, icqMD.Seq); err != nil { return err } + case wire.ICQDBQueryMetaReqSearchByEmail3: + req := wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3{} + if err := wire.UnmarshalLE(&req, buf); err != nil { + return err + } + if err := rt.ICQService.FindByEmail3(ctx, sess, req, icqMD.Seq); err != nil { + return err + } case wire.ICQDBQueryMetaReqSearchByDetails: req := wire.ICQ_0x07D0_0x0515_DBQueryMetaReqSearchByDetails{} if err := wire.UnmarshalLE(&req, buf); err != nil { @@ -150,6 +169,14 @@ func (rt ICQHandler) DBQuery(ctx context.Context, sess *state.Session, inFrame w if err := rt.ICQService.FindByInterests(ctx, sess, req, icqMD.Seq); err != nil { return err } + case wire.ICQDBQueryMetaReqSearchWhitePages2: + req := wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2{} + if err := wire.UnmarshalLE(&req, buf); err != nil { + return err + } + if err := rt.ICQService.FindByWhitePages2(ctx, sess, req, icqMD.Seq); err != nil { + return err + } case wire.ICQDBQueryMetaReqSetBasicInfo: req := wire.ICQ_0x07D0_0x03EA_DBQueryMetaReqSetBasicInfo{} if err := wire.UnmarshalLE(&req, buf); err != nil { diff --git a/server/oscar/handler/icq_test.go b/server/oscar/handler/icq_test.go index fc8e58a1..acf49abc 100644 --- a/server/oscar/handler/icq_test.go +++ b/server/oscar/handler/icq_test.go @@ -34,23 +34,26 @@ func TestICQHandler_DBQuery(t *testing.T) { wantErr error } type allMockParams struct { - deleteMsgReq *mockParam - findByDetails *mockParam - findByEmail *mockParam - findByInterests *mockParam - findByUIN *mockParam - fullUserInfo *mockParam - offlineMsgReq *mockParam - setAffiliations *mockParam - setBasicInfo *mockParam - setEmails *mockParam - setInterests *mockParam - setMoreInfo *mockParam - setPermissions *mockParam - setUserNotes *mockParam - setWorkInfo *mockParam - shortUserInfo *mockParam - xmlReqData *mockParam + deleteMsgReq *mockParam + findByDetails *mockParam + findByEmail *mockParam + findByEmail3 *mockParam + findByInterests *mockParam + findByUIN *mockParam + findByUIN2 *mockParam + findByWhitePages2 *mockParam + fullUserInfo *mockParam + offlineMsgReq *mockParam + setAffiliations *mockParam + setBasicInfo *mockParam + setEmails *mockParam + setInterests *mockParam + setMoreInfo *mockParam + setPermissions *mockParam + setUserNotes *mockParam + setWorkInfo *mockParam + shortUserInfo *mockParam + xmlReqData *mockParam } tests := []struct { name string @@ -64,7 +67,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -96,7 +99,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -128,7 +131,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -160,7 +163,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -192,7 +195,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -224,7 +227,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -249,6 +252,46 @@ func TestICQHandler_DBQuery(t *testing.T) { }, }, }, + { + name: "MetaReqSearchByUIN2 - happy path", + reqParams: reqParams{ + sess: &state.Session{}, + inBody: wire.SNAC_0x15_0x02_BQuery{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + Message: ICQMetaRequest{ + ICQMetadata: wire.ICQMetadata{ + ReqType: wire.ICQDBQueryMetaReq, + Seq: 1, + }, + ReqSubType: wire.ICQDBQueryMetaReqSearchByUIN2, + MetaRequest: wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(1, uint16(1)), + }, + }, + }, + }, + }), + }, + }, + }, + seq: 1, + }, + allMockParams: allMockParams{ + findByUIN2: &mockParam{ + req: wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(1, uint16(1)), + }, + }, + }, + }, + }, + }, { name: "MetaReqSearchByEmail - happy path", reqParams: reqParams{ @@ -256,7 +299,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -281,6 +324,46 @@ func TestICQHandler_DBQuery(t *testing.T) { }, }, }, + { + name: "MetaReqSearchByEmail3 - happy path", + reqParams: reqParams{ + sess: &state.Session{}, + inBody: wire.SNAC_0x15_0x02_BQuery{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + Message: ICQMetaRequest{ + ICQMetadata: wire.ICQMetadata{ + ReqType: wire.ICQDBQueryMetaReq, + Seq: 1, + }, + ReqSubType: wire.ICQDBQueryMetaReqSearchByEmail3, + MetaRequest: wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(1, uint16(1)), + }, + }, + }, + }, + }), + }, + }, + }, + seq: 1, + }, + allMockParams: allMockParams{ + findByEmail3: &mockParam{ + req: wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(1, uint16(1)), + }, + }, + }, + }, + }, + }, { name: "MetaReqSearchByDetails - happy path", reqParams: reqParams{ @@ -288,7 +371,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -320,7 +403,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -345,6 +428,46 @@ func TestICQHandler_DBQuery(t *testing.T) { }, }, }, + { + name: "MetaReqSearchWhitePages2 - happy path", + reqParams: reqParams{ + sess: &state.Session{}, + inBody: wire.SNAC_0x15_0x02_BQuery{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + Message: ICQMetaRequest{ + ICQMetadata: wire.ICQMetadata{ + ReqType: wire.ICQDBQueryMetaReq, + Seq: 1, + }, + ReqSubType: wire.ICQDBQueryMetaReqSearchWhitePages2, + MetaRequest: wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(1, uint16(1)), + }, + }, + }, + }, + }), + }, + }, + }, + seq: 1, + }, + allMockParams: allMockParams{ + findByWhitePages2: &mockParam{ + req: wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2{ + TLVRestBlock: wire.TLVRestBlock{ + TLVList: wire.TLVList{ + wire.NewTLVBE(1, uint16(1)), + }, + }, + }, + }, + }, + }, { name: "MetaReqSetBasicInfo - happy path", reqParams: reqParams{ @@ -352,7 +475,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -384,7 +507,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -416,7 +539,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -448,7 +571,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -480,7 +603,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -526,7 +649,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -572,7 +695,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -634,7 +757,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -657,7 +780,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryMetaReq, @@ -681,7 +804,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQMetadataWithSubType{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryOfflineMsgReq, @@ -705,7 +828,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: wire.ICQMetadataWithSubType{ ICQMetadata: wire.ICQMetadata{ ReqType: wire.ICQDBQueryDeleteMsgReq, @@ -729,7 +852,7 @@ func TestICQHandler_DBQuery(t *testing.T) { inBody: wire.SNAC_0x15_0x02_BQuery{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ + wire.NewTLVBE(wire.ICQTLVTagsMetadata, wire.ICQMessageReplyEnvelope{ Message: ICQMetaRequest{ ICQMetadata: wire.ICQMetadata{ ReqType: 0x13B4, @@ -772,10 +895,18 @@ func TestICQHandler_DBQuery(t *testing.T) { icqService.EXPECT(). FindByUIN(mock.Anything, tt.reqParams.sess, tt.allMockParams.findByUIN.req, tt.reqParams.seq). Return(tt.allMockParams.findByUIN.wantErr) + case tt.allMockParams.findByUIN2 != nil: + icqService.EXPECT(). + FindByUIN2(mock.Anything, tt.reqParams.sess, tt.allMockParams.findByUIN2.req, tt.reqParams.seq). + Return(tt.allMockParams.findByUIN2.wantErr) case tt.allMockParams.findByEmail != nil: icqService.EXPECT(). FindByEmail(mock.Anything, tt.reqParams.sess, tt.allMockParams.findByEmail.req, tt.reqParams.seq). Return(tt.allMockParams.findByEmail.wantErr) + case tt.allMockParams.findByEmail3 != nil: + icqService.EXPECT(). + FindByEmail3(mock.Anything, tt.reqParams.sess, tt.allMockParams.findByEmail3.req, tt.reqParams.seq). + Return(tt.allMockParams.findByEmail3.wantErr) case tt.allMockParams.findByDetails != nil: icqService.EXPECT(). FindByDetails(mock.Anything, tt.reqParams.sess, tt.allMockParams.findByDetails.req, tt.reqParams.seq). @@ -784,6 +915,10 @@ func TestICQHandler_DBQuery(t *testing.T) { icqService.EXPECT(). FindByInterests(mock.Anything, tt.reqParams.sess, tt.allMockParams.findByInterests.req, tt.reqParams.seq). Return(tt.allMockParams.findByInterests.wantErr) + case tt.allMockParams.findByWhitePages2 != nil: + icqService.EXPECT(). + FindByWhitePages2(mock.Anything, tt.reqParams.sess, tt.allMockParams.findByWhitePages2.req, tt.reqParams.seq). + Return(tt.allMockParams.findByWhitePages2.wantErr) case tt.allMockParams.setBasicInfo != nil: icqService.EXPECT(). SetBasicInfo(mock.Anything, tt.reqParams.sess, tt.allMockParams.setBasicInfo.req, tt.reqParams.seq). diff --git a/server/oscar/handler/locate_test.go b/server/oscar/handler/locate_test.go index 81983dfb..a45f0f6b 100644 --- a/server/oscar/handler/locate_test.go +++ b/server/oscar/handler/locate_test.go @@ -48,7 +48,7 @@ func TestLocateHandler_RightsQuery(t *testing.T) { Body: wire.SNAC_0x02_0x03_LocateRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, uint16(1000)), + wire.NewTLVBE(0x01, uint16(1000)), }, }, }, diff --git a/server/oscar/handler/mock_feedbag_test.go b/server/oscar/handler/mock_feedbag_test.go index b0bbd24d..81e13bb8 100644 --- a/server/oscar/handler/mock_feedbag_test.go +++ b/server/oscar/handler/mock_feedbag_test.go @@ -200,6 +200,55 @@ func (_c *mockFeedbagService_QueryIfModified_Call) RunAndReturn(run func(context return _c } +// RespondAuthorizeToHost provides a mock function with given fields: ctx, sess, inFrame, inBody +func (_m *mockFeedbagService) RespondAuthorizeToHost(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, inBody wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost) error { + ret := _m.Called(ctx, sess, inFrame, inBody) + + if len(ret) == 0 { + panic("no return value specified for RespondAuthorizeToHost") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *state.Session, wire.SNACFrame, wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost) error); ok { + r0 = rf(ctx, sess, inFrame, inBody) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockFeedbagService_RespondAuthorizeToHost_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RespondAuthorizeToHost' +type mockFeedbagService_RespondAuthorizeToHost_Call struct { + *mock.Call +} + +// RespondAuthorizeToHost is a helper method to define mock.On call +// - ctx context.Context +// - sess *state.Session +// - inFrame wire.SNACFrame +// - inBody wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost +func (_e *mockFeedbagService_Expecter) RespondAuthorizeToHost(ctx interface{}, sess interface{}, inFrame interface{}, inBody interface{}) *mockFeedbagService_RespondAuthorizeToHost_Call { + return &mockFeedbagService_RespondAuthorizeToHost_Call{Call: _e.mock.On("RespondAuthorizeToHost", ctx, sess, inFrame, inBody)} +} + +func (_c *mockFeedbagService_RespondAuthorizeToHost_Call) Run(run func(ctx context.Context, sess *state.Session, inFrame wire.SNACFrame, inBody wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost)) *mockFeedbagService_RespondAuthorizeToHost_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*state.Session), args[2].(wire.SNACFrame), args[3].(wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost)) + }) + return _c +} + +func (_c *mockFeedbagService_RespondAuthorizeToHost_Call) Return(_a0 error) *mockFeedbagService_RespondAuthorizeToHost_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockFeedbagService_RespondAuthorizeToHost_Call) RunAndReturn(run func(context.Context, *state.Session, wire.SNACFrame, wire.SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost) error) *mockFeedbagService_RespondAuthorizeToHost_Call { + _c.Call.Return(run) + return _c +} + // RightsQuery provides a mock function with given fields: ctx, inFrame func (_m *mockFeedbagService) RightsQuery(ctx context.Context, inFrame wire.SNACFrame) wire.SNACMessage { ret := _m.Called(ctx, inFrame) diff --git a/server/oscar/handler/mock_icq_service_test.go b/server/oscar/handler/mock_icq_service_test.go index e1d5cf6e..cdb240b2 100644 --- a/server/oscar/handler/mock_icq_service_test.go +++ b/server/oscar/handler/mock_icq_service_test.go @@ -170,6 +170,55 @@ func (_c *mockICQService_FindByEmail_Call) RunAndReturn(run func(context.Context return _c } +// FindByEmail3 provides a mock function with given fields: ctx, sess, req, seq +func (_m *mockICQService) FindByEmail3(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3, seq uint16) error { + ret := _m.Called(ctx, sess, req, seq) + + if len(ret) == 0 { + panic("no return value specified for FindByEmail3") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *state.Session, wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3, uint16) error); ok { + r0 = rf(ctx, sess, req, seq) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockICQService_FindByEmail3_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindByEmail3' +type mockICQService_FindByEmail3_Call struct { + *mock.Call +} + +// FindByEmail3 is a helper method to define mock.On call +// - ctx context.Context +// - sess *state.Session +// - req wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3 +// - seq uint16 +func (_e *mockICQService_Expecter) FindByEmail3(ctx interface{}, sess interface{}, req interface{}, seq interface{}) *mockICQService_FindByEmail3_Call { + return &mockICQService_FindByEmail3_Call{Call: _e.mock.On("FindByEmail3", ctx, sess, req, seq)} +} + +func (_c *mockICQService_FindByEmail3_Call) Run(run func(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3, seq uint16)) *mockICQService_FindByEmail3_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*state.Session), args[2].(wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3), args[3].(uint16)) + }) + return _c +} + +func (_c *mockICQService_FindByEmail3_Call) Return(_a0 error) *mockICQService_FindByEmail3_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockICQService_FindByEmail3_Call) RunAndReturn(run func(context.Context, *state.Session, wire.ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3, uint16) error) *mockICQService_FindByEmail3_Call { + _c.Call.Return(run) + return _c +} + // FindByInterests provides a mock function with given fields: ctx, sess, req, seq func (_m *mockICQService) FindByInterests(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages, seq uint16) error { ret := _m.Called(ctx, sess, req, seq) @@ -268,6 +317,104 @@ func (_c *mockICQService_FindByUIN_Call) RunAndReturn(run func(context.Context, return _c } +// FindByUIN2 provides a mock function with given fields: ctx, sess, req, seq +func (_m *mockICQService) FindByUIN2(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2, seq uint16) error { + ret := _m.Called(ctx, sess, req, seq) + + if len(ret) == 0 { + panic("no return value specified for FindByUIN2") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *state.Session, wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2, uint16) error); ok { + r0 = rf(ctx, sess, req, seq) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockICQService_FindByUIN2_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindByUIN2' +type mockICQService_FindByUIN2_Call struct { + *mock.Call +} + +// FindByUIN2 is a helper method to define mock.On call +// - ctx context.Context +// - sess *state.Session +// - req wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2 +// - seq uint16 +func (_e *mockICQService_Expecter) FindByUIN2(ctx interface{}, sess interface{}, req interface{}, seq interface{}) *mockICQService_FindByUIN2_Call { + return &mockICQService_FindByUIN2_Call{Call: _e.mock.On("FindByUIN2", ctx, sess, req, seq)} +} + +func (_c *mockICQService_FindByUIN2_Call) Run(run func(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2, seq uint16)) *mockICQService_FindByUIN2_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*state.Session), args[2].(wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2), args[3].(uint16)) + }) + return _c +} + +func (_c *mockICQService_FindByUIN2_Call) Return(_a0 error) *mockICQService_FindByUIN2_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockICQService_FindByUIN2_Call) RunAndReturn(run func(context.Context, *state.Session, wire.ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2, uint16) error) *mockICQService_FindByUIN2_Call { + _c.Call.Return(run) + return _c +} + +// FindByWhitePages2 provides a mock function with given fields: ctx, sess, req, seq +func (_m *mockICQService) FindByWhitePages2(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2, seq uint16) error { + ret := _m.Called(ctx, sess, req, seq) + + if len(ret) == 0 { + panic("no return value specified for FindByWhitePages2") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *state.Session, wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2, uint16) error); ok { + r0 = rf(ctx, sess, req, seq) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// mockICQService_FindByWhitePages2_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FindByWhitePages2' +type mockICQService_FindByWhitePages2_Call struct { + *mock.Call +} + +// FindByWhitePages2 is a helper method to define mock.On call +// - ctx context.Context +// - sess *state.Session +// - req wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2 +// - seq uint16 +func (_e *mockICQService_Expecter) FindByWhitePages2(ctx interface{}, sess interface{}, req interface{}, seq interface{}) *mockICQService_FindByWhitePages2_Call { + return &mockICQService_FindByWhitePages2_Call{Call: _e.mock.On("FindByWhitePages2", ctx, sess, req, seq)} +} + +func (_c *mockICQService_FindByWhitePages2_Call) Run(run func(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2, seq uint16)) *mockICQService_FindByWhitePages2_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*state.Session), args[2].(wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2), args[3].(uint16)) + }) + return _c +} + +func (_c *mockICQService_FindByWhitePages2_Call) Return(_a0 error) *mockICQService_FindByWhitePages2_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *mockICQService_FindByWhitePages2_Call) RunAndReturn(run func(context.Context, *state.Session, wire.ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2, uint16) error) *mockICQService_FindByWhitePages2_Call { + _c.Call.Return(run) + return _c +} + // FullUserInfo provides a mock function with given fields: ctx, sess, req, seq func (_m *mockICQService) FullUserInfo(ctx context.Context, sess *state.Session, req wire.ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN, seq uint16) error { ret := _m.Called(ctx, sess, req, seq) diff --git a/server/oscar/handler/oservice_test.go b/server/oscar/handler/oservice_test.go index 05ab2043..db523b60 100644 --- a/server/oscar/handler/oservice_test.go +++ b/server/oscar/handler/oservice_test.go @@ -65,7 +65,7 @@ func TestOServiceBOSHandler_ServiceRequest(t *testing.T) { Body: wire.SNAC_0x01_0x05_OServiceServiceResponse{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, uint16(1000)), + wire.NewTLVBE(0x01, uint16(1000)), }, }, }, @@ -262,7 +262,7 @@ func TestOServiceHandler_RateParamsSubAdd(t *testing.T) { Body: wire.SNAC_0x01_0x08_OServiceRateParamsSubAdd{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, []byte{1, 2, 3, 4}), + wire.NewTLVBE(0x01, []byte{1, 2, 3, 4}), }, }, }, @@ -296,7 +296,7 @@ func TestOServiceHandler_SetUserInfoFields(t *testing.T) { Body: wire.SNAC_0x01_0x1E_OServiceSetUserInfoFields{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, []byte{1, 2, 3, 4}), + wire.NewTLVBE(0x01, []byte{1, 2, 3, 4}), }, }, }, diff --git a/server/oscar/handler/permit_deny_test.go b/server/oscar/handler/permit_deny_test.go index da145287..dd8e55b6 100644 --- a/server/oscar/handler/permit_deny_test.go +++ b/server/oscar/handler/permit_deny_test.go @@ -27,7 +27,7 @@ func TestPermitDenyHandler_RightsQuery(t *testing.T) { Body: wire.SNAC_0x09_0x03_PermitDenyRightsReply{ TLVRestBlock: wire.TLVRestBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, uint16(1000)), + wire.NewTLVBE(0x01, uint16(1000)), }, }, }, diff --git a/server/oscar/handler/routes.go b/server/oscar/handler/routes.go index 21c98b26..37f39c1c 100644 --- a/server/oscar/handler/routes.go +++ b/server/oscar/handler/routes.go @@ -53,6 +53,7 @@ func NewBOSRouter(h Handlers) oscar.Router { router.Register(wire.Feedbag, wire.FeedbagStartCluster, h.FeedbagHandler.StartCluster) router.Register(wire.Feedbag, wire.FeedbagUpdateItem, h.FeedbagHandler.UpdateItem) router.Register(wire.Feedbag, wire.FeedbagUse, h.FeedbagHandler.Use) + router.Register(wire.Feedbag, wire.FeedbagRespondAuthorizeToHost, h.FeedbagHandler.RespondAuthorizeToHost) router.Register(wire.ICQ, wire.ICQDBQuery, h.ICQHandler.DBQuery) diff --git a/state/chat.go b/state/chat.go index 4011f41b..145b8fc3 100644 --- a/state/chat.go +++ b/state/chat.go @@ -104,19 +104,19 @@ func (c ChatRoom) TLVList() []wire.TLV { // - 4 Instancing Allowed // - 8 Occupant Peek Allowed // It's unclear what effect they actually have. - wire.NewTLV(wire.ChatRoomTLVFlags, uint16(15)), - wire.NewTLV(wire.ChatRoomTLVCreateTime, uint32(c.createTime.Unix())), - wire.NewTLV(wire.ChatRoomTLVMaxMsgLen, uint16(1024)), - wire.NewTLV(wire.ChatRoomTLVMaxOccupancy, uint16(100)), + wire.NewTLVBE(wire.ChatRoomTLVFlags, uint16(15)), + wire.NewTLVBE(wire.ChatRoomTLVCreateTime, uint32(c.createTime.Unix())), + wire.NewTLVBE(wire.ChatRoomTLVMaxMsgLen, uint16(1024)), + wire.NewTLVBE(wire.ChatRoomTLVMaxOccupancy, uint16(100)), // From protocols/oscar/family_chatnav.c in lib purple, these are the // room creation permission values: // - 0 creation not allowed // - 1 room creation allowed // - 2 exchange creation allowed // It's unclear what effect they actually have. - wire.NewTLV(wire.ChatRoomTLVNavCreatePerms, uint8(2)), - wire.NewTLV(wire.ChatRoomTLVFullyQualifiedName, c.name), - wire.NewTLV(wire.ChatRoomTLVRoomName, c.name), - wire.NewTLV(wire.ChatRoomTLVMaxMsgVisLen, uint16(1024)), + wire.NewTLVBE(wire.ChatRoomTLVNavCreatePerms, uint8(2)), + wire.NewTLVBE(wire.ChatRoomTLVFullyQualifiedName, c.name), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, c.name), + wire.NewTLVBE(wire.ChatRoomTLVMaxMsgVisLen, uint16(1024)), } } diff --git a/state/chat_test.go b/state/chat_test.go index 043634ca..e4d5d313 100644 --- a/state/chat_test.go +++ b/state/chat_test.go @@ -13,14 +13,14 @@ func TestChatRoom_TLVList(t *testing.T) { have := room.TLVList() want := []wire.TLV{ - wire.NewTLV(wire.ChatRoomTLVFlags, uint16(15)), - wire.NewTLV(wire.ChatRoomTLVCreateTime, uint32(room.createTime.Unix())), - wire.NewTLV(wire.ChatRoomTLVMaxMsgLen, uint16(1024)), - wire.NewTLV(wire.ChatRoomTLVMaxOccupancy, uint16(100)), - wire.NewTLV(wire.ChatRoomTLVNavCreatePerms, uint8(2)), - wire.NewTLV(wire.ChatRoomTLVFullyQualifiedName, room.name), - wire.NewTLV(wire.ChatRoomTLVRoomName, room.name), - wire.NewTLV(wire.ChatRoomTLVMaxMsgVisLen, uint16(1024)), + wire.NewTLVBE(wire.ChatRoomTLVFlags, uint16(15)), + wire.NewTLVBE(wire.ChatRoomTLVCreateTime, uint32(room.createTime.Unix())), + wire.NewTLVBE(wire.ChatRoomTLVMaxMsgLen, uint16(1024)), + wire.NewTLVBE(wire.ChatRoomTLVMaxOccupancy, uint16(100)), + wire.NewTLVBE(wire.ChatRoomTLVNavCreatePerms, uint8(2)), + wire.NewTLVBE(wire.ChatRoomTLVFullyQualifiedName, room.name), + wire.NewTLVBE(wire.ChatRoomTLVRoomName, room.name), + wire.NewTLVBE(wire.ChatRoomTLVMaxMsgVisLen, uint16(1024)), } assert.Equal(t, want, have) diff --git a/state/session.go b/state/session.go index 8e8d6b57..282f79cd 100644 --- a/state/session.go +++ b/state/session.go @@ -249,32 +249,32 @@ func (s *Session) userInfo() wire.TLVList { tlvs := wire.TLVList{} // sign-in timestamp - tlvs.Append(wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(s.signonTime.Unix()))) + tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(s.signonTime.Unix()))) // user info flags uFlags := s.userInfoBitmask if s.awayMessage != "" { uFlags |= wire.OServiceUserFlagUnavailable } - tlvs.Append(wire.NewTLV(wire.OServiceUserInfoUserFlags, uFlags)) + tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uFlags)) // user status flags - tlvs.Append(wire.NewTLV(wire.OServiceUserInfoStatus, s.userStatusBitmask)) + tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoStatus, s.userStatusBitmask)) // idle status if s.idle { - tlvs.Append(wire.NewTLV(wire.OServiceUserInfoIdleTime, uint16(s.nowFn().Sub(s.idleTime).Minutes()))) + tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoIdleTime, uint16(s.nowFn().Sub(s.idleTime).Minutes()))) } // ICQ direct-connect info. The TLV is required for buddy arrival events to // work in ICQ, even if the values are set to default. if s.userInfoBitmask&wire.OServiceUserFlagICQ == wire.OServiceUserFlagICQ { - tlvs.Append(wire.NewTLV(wire.OServiceUserInfoICQDC, wire.ICQDCInfo{})) + tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoICQDC, wire.ICQDCInfo{})) } // capabilities (buddy icon, chat, etc...) if len(s.caps) > 0 { - tlvs.Append(wire.NewTLV(wire.OServiceUserInfoOscarCaps, s.caps)) + tlvs.Append(wire.NewTLVBE(wire.OServiceUserInfoOscarCaps, s.caps)) } return tlvs diff --git a/state/session_test.go b/state/session_test.go index 2de82e39..41f1137b 100644 --- a/state/session_test.go +++ b/state/session_test.go @@ -80,9 +80,9 @@ func TestSession_TLVUserInfo(t *testing.T) { WarningLevel: 10, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(1)), - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0x0010)), - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0000)), + wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)), }, }, }, @@ -102,10 +102,10 @@ func TestSession_TLVUserInfo(t *testing.T) { ScreenName: "1000003", TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(1)), - wire.NewTLV(wire.OServiceUserInfoUserFlags, wire.OServiceUserFlagOSCARFree|wire.OServiceUserFlagICQ), - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0000)), - wire.NewTLV(wire.OServiceUserInfoICQDC, wire.ICQDCInfo{}), + wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, wire.OServiceUserFlagOSCARFree|wire.OServiceUserFlagICQ), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)), + wire.NewTLVBE(wire.OServiceUserInfoICQDC, wire.ICQDCInfo{}), }, }, }, @@ -121,9 +121,9 @@ func TestSession_TLVUserInfo(t *testing.T) { want: wire.TLVUserInfo{ TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(1)), - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0x30)), - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0000)), + wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x30)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)), }, }, }, @@ -139,9 +139,9 @@ func TestSession_TLVUserInfo(t *testing.T) { want: wire.TLVUserInfo{ TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(1)), - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0x0010)), - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0100)), + wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0100)), }, }, }, @@ -165,10 +165,10 @@ func TestSession_TLVUserInfo(t *testing.T) { want: wire.TLVUserInfo{ TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(0)), - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0x0010)), - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0000)), - wire.NewTLV(wire.OServiceUserInfoIdleTime, uint16(6)), + wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(0)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)), + wire.NewTLVBE(wire.OServiceUserInfoIdleTime, uint16(6)), }, }, }, @@ -185,9 +185,9 @@ func TestSession_TLVUserInfo(t *testing.T) { want: wire.TLVUserInfo{ TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(1)), - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0x0010)), - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0000)), + wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)), }, }, }, @@ -214,10 +214,10 @@ func TestSession_TLVUserInfo(t *testing.T) { want: wire.TLVUserInfo{ TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(1)), - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0x0010)), - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0000)), - wire.NewTLV(wire.OServiceUserInfoOscarCaps, []byte{ + wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)), + wire.NewTLVBE(wire.OServiceUserInfoOscarCaps, []byte{ // chat: "748F2420-6287-11D1-8222-444553540000" 0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1, 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00, @@ -240,9 +240,9 @@ func TestSession_TLVUserInfo(t *testing.T) { WarningLevel: 0, TLVBlock: wire.TLVBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.OServiceUserInfoSignonTOD, uint32(1)), - wire.NewTLV(wire.OServiceUserInfoUserFlags, uint16(0x0010)), - wire.NewTLV(wire.OServiceUserInfoStatus, uint32(0x0000)), + wire.NewTLVBE(wire.OServiceUserInfoSignonTOD, uint32(1)), + wire.NewTLVBE(wire.OServiceUserInfoUserFlags, uint16(0x0010)), + wire.NewTLVBE(wire.OServiceUserInfoStatus, uint32(0x0000)), }, }, }, diff --git a/state/user_store.go b/state/user_store.go index 4f08aed9..fdb52bea 100644 --- a/state/user_store.go +++ b/state/user_store.go @@ -103,11 +103,9 @@ func (f SQLiteUserStore) AllUsers() ([]User, error) { return users, nil } -// FindByUIN returns a user where the UIN matches the ident screen name. +// FindByUIN returns a user with a matching UIN. func (f SQLiteUserStore) FindByUIN(UIN uint32) (User, error) { - users, err := getUsers(func() (string, []any) { - return `identScreenName = ?`, []any{strconv.Itoa(int(UIN))} - }, f.db) + users, err := f.queryUsers(`identScreenName = ?`, []any{strconv.Itoa(int(UIN))}) if err != nil { return User{}, fmt.Errorf("FindByUIN: %w", err) } @@ -121,9 +119,7 @@ func (f SQLiteUserStore) FindByUIN(UIN uint32) (User, error) { // FindByEmail returns a user with a matching email address. func (f SQLiteUserStore) FindByEmail(email string) (User, error) { - users, err := getUsers(func() (string, []any) { - return `icq_basicInfo_emailAddress = ?`, []any{email} - }, f.db) + users, err := f.queryUsers(`icq_basicInfo_emailAddress = ?`, []any{email}) if err != nil { return User{}, fmt.Errorf("FindByEmail: %w", err) } @@ -135,63 +131,89 @@ func (f SQLiteUserStore) FindByEmail(email string) (User, error) { return users[0], nil } -// FindByDetails returns a user with either a matching first name, last name, or nickname. +// FindByDetails returns users with either a matching first name, last name, +// and nickname. Empty values are not included in the search parameters. func (f SQLiteUserStore) FindByDetails(firstName, lastName, nickName string) ([]User, error) { - users, err := getUsers(func() (string, []any) { - var conds []string - var vals []any - if firstName != "" { - conds = append(conds, `LOWER(icq_basicInfo_firstName) = LOWER(?)`) - vals = append(vals, firstName) - } - if lastName != "" { - conds = append(conds, `LOWER(icq_basicInfo_lastName) = LOWER(?)`) - vals = append(vals, lastName) - } - if nickName != "" { - conds = append(conds, `LOWER(icq_basicInfo_nickName) = LOWER(?)`) - vals = append(vals, nickName) - } - return strings.Join(conds, " AND "), vals - }, f.db) + var args []any + var clauses []string + + if firstName != "" { + args = append(args, firstName) + clauses = append(clauses, `LOWER(icq_basicInfo_firstName) = LOWER(?)`) + } + + if lastName != "" { + args = append(args, lastName) + clauses = append(clauses, `LOWER(icq_basicInfo_lastName) = LOWER(?)`) + } + + if nickName != "" { + args = append(args, nickName) + clauses = append(clauses, `LOWER(icq_basicInfo_nickName) = LOWER(?)`) + } + + whereClause := strings.Join(clauses, " AND ") + + users, err := f.queryUsers(whereClause, args) if err != nil { err = fmt.Errorf("FindByDetails: %w", err) } + return users, nil } -// FindByInterests returns a user who has at least one matching interest. +// FindByInterests returns users who have at least one matching interest. func (f SQLiteUserStore) FindByInterests(code uint16, keywords []string) ([]User, error) { - users, err := getUsers(func() (string, []any) { - var conds []string - var vals []any - - for i := 1; i <= 4; i++ { - var subConds []string - vals = append(vals, code) - for _, key := range keywords { - subConds = append(subConds, fmt.Sprintf("icq_interests_keyword%d LIKE ?", i)) - vals = append(vals, "%"+key+"%") - } - conds = append(conds, fmt.Sprintf("(icq_interests_code%d = ? AND (%s))", i, strings.Join(subConds, " OR "))) + var args []any + var clauses []string + + for i := 1; i <= 4; i++ { + var subClauses []string + args = append(args, code) + for _, key := range keywords { + subClauses = append(subClauses, fmt.Sprintf("icq_interests_keyword%d LIKE ?", i)) + args = append(args, "%"+key+"%") } + clauses = append(clauses, fmt.Sprintf("(icq_interests_code%d = ? AND (%s))", i, strings.Join(subClauses, " OR "))) + } - return strings.Join(conds, " OR "), vals - }, f.db) + cond := strings.Join(clauses, " OR ") + + users, err := f.queryUsers(cond, args) if err != nil { err = fmt.Errorf("FindByInterests: %w", err) } + + return users, nil +} + +// FindByKeyword returns users with matching interest keyword across all +// interest categories. +func (f SQLiteUserStore) FindByKeyword(keyword string) ([]User, error) { + var args []any + var clauses []string + + for i := 1; i <= 4; i++ { + args = append(args, "%"+keyword+"%") + clauses = append(clauses, fmt.Sprintf("icq_interests_keyword%d LIKE ?", i)) + } + + whereClause := strings.Join(clauses, " OR ") + + users, err := f.queryUsers(whereClause, args) + if err != nil { + err = fmt.Errorf("FindByKeyword: %w", err) + } + return users, nil } // User looks up a user by screen name. It populates the User record with // credentials that can be used to validate the user's password. func (f SQLiteUserStore) User(screenName IdentScreenName) (*User, error) { - users, err := getUsers(func() (string, []any) { - return `identScreenName = ?`, []any{screenName.String()} - }, f.db) + users, err := f.queryUsers(`identScreenName = ?`, []any{screenName.String()}) if err != nil { - return nil, fmt.Errorf("user: %w", err) + return nil, fmt.Errorf("User: %w", err) } if len(users) == 0 { @@ -201,17 +223,10 @@ func (f SQLiteUserStore) User(screenName IdentScreenName) (*User, error) { return &users[0], nil } -type filterFN func() (string, []any) - -type queryer interface { - Query(query string, args ...any) (*sql.Rows, error) -} - -// getUsers fetches users from the database by their screen name. -func getUsers(filterFN filterFN, tx queryer) ([]User, error) { - - cond, parms := filterFN() - +// queryUsers retrieves a list of users from the database based on the +// specified WHERE clause and query parameters. Returns a slice of User objects +// or an error if the query fails. +func (f SQLiteUserStore) queryUsers(whereClause string, queryParams []any) ([]User, error) { q := ` SELECT identScreenName, @@ -282,8 +297,8 @@ func getUsers(filterFN filterFN, tx queryer) ([]User, error) { FROM users WHERE %s ` - q = fmt.Sprintf(q, cond) - rows, err := tx.Query(q, parms...) + q = fmt.Sprintf(q, whereClause) + rows, err := f.db.Query(q, queryParams...) if err != nil { return nil, err } @@ -1306,7 +1321,7 @@ func (f SQLiteUserStore) BuddyIconRefByName(screenName IdentScreenName) (*wire.B if err := wire.UnmarshalBE(&item.TLVLBlock, bytes.NewBuffer(attrs)); err != nil { return nil, err } - b, hasBuf := item.Slice(wire.FeedbagAttributesBartInfo) + b, hasBuf := item.Bytes(wire.FeedbagAttributesBartInfo) if !hasBuf { return nil, errors.New("unable to extract icon payload") } diff --git a/state/user_store_test.go b/state/user_store_test.go index a3f6303c..852a3c05 100644 --- a/state/user_store_test.go +++ b/state/user_store_test.go @@ -72,7 +72,7 @@ func TestFeedbagDelete(t *testing.T) { Name: "spimmer1234", TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(0x01, uint16(1000)), + wire.NewTLVBE(0x01, uint16(1000)), }, }, }, @@ -1443,6 +1443,82 @@ func TestSQLiteUserStore_FindByInterests(t *testing.T) { }) } +func TestSQLiteUserStore_FindByKeyword(t *testing.T) { + // Cleanup after test + defer func() { + assert.NoError(t, os.Remove(testFile)) + }() + + // Initialize the SQLiteUserStore with a test database file + f, err := NewSQLiteUserStore(testFile) + assert.NoError(t, err) + + // Create and set up test users with different interests + user1 := User{ + IdentScreenName: NewIdentScreenName("user1"), + } + err = f.InsertUser(user1) + assert.NoError(t, err) + interests1 := ICQInterests{ + Keyword1: "Coding", + Keyword2: "Music", + } + err = f.SetInterests(user1.IdentScreenName, interests1) + assert.NoError(t, err) + + user2 := User{ + IdentScreenName: NewIdentScreenName("user2"), + } + err = f.InsertUser(user2) + assert.NoError(t, err) + interests2 := ICQInterests{ + Keyword1: "Coding", + Keyword3: "Gaming", + } + err = f.SetInterests(user2.IdentScreenName, interests2) + assert.NoError(t, err) + + user3 := User{ + IdentScreenName: NewIdentScreenName("user3"), + } + err = f.InsertUser(user3) + assert.NoError(t, err) + interests3 := ICQInterests{ + Keyword3: "Music", + Keyword4: "Travel", + } + err = f.SetInterests(user3.IdentScreenName, interests3) + assert.NoError(t, err) + + // Helper function to check if a user with a specific IdentScreenName exists in the results + containsUserWithScreenName := func(users []User, screenName IdentScreenName) bool { + for _, user := range users { + if user.IdentScreenName == screenName { + return true + } + } + return false + } + + t.Run("Find Users by Keyword", func(t *testing.T) { + // Search for users interested in "Music" + users, err := f.FindByKeyword("Music") + assert.NoError(t, err) + assert.Len(t, users, 2) + + // Check that the correct users are returned by IdentScreenName + assert.True(t, containsUserWithScreenName(users, user1.IdentScreenName)) + assert.True(t, containsUserWithScreenName(users, user3.IdentScreenName)) + }) + + t.Run("No Users Found", func(t *testing.T) { + // Search for users interested in a keyword that no user has + users, err := f.FindByKeyword("Knitting") + assert.NoError(t, err) + assert.Empty(t, users) + }) +} + func TestSQLiteUserStore_FindByDetails(t *testing.T) { // Cleanup after test defer func() { @@ -1813,7 +1889,7 @@ func TestSQLiteUserStore_BuddyIconRefByNameExistingRef(t *testing.T) { ClassID: wire.FeedbagClassIdBart, TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: testHash, }), }, @@ -1850,7 +1926,7 @@ func TestSQLiteUserStore_BuddyIconRefByNameMissingRef(t *testing.T) { ClassID: wire.FeedbagClassIdBart, TLVLBlock: wire.TLVLBlock{ TLVList: wire.TLVList{ - wire.NewTLV(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ + wire.NewTLVBE(wire.FeedbagAttributesBartInfo, wire.BARTInfo{ Hash: testHash, }), }, diff --git a/wire/decode_test.go b/wire/decode_test.go index 00c896fc..0d9e74d3 100644 --- a/wire/decode_test.go +++ b/wire/decode_test.go @@ -287,8 +287,8 @@ func TestUnmarshal(t *testing.T) { Val []TLV }{ Val: []TLV{ - NewTLV(10, uint16(1234)), - NewTLV(20, uint16(1234)), + NewTLVBE(10, uint16(1234)), + NewTLVBE(20, uint16(1234)), }, }, given: []byte{0x0, 0xa, 0x0, 0x2, 0x4, 0xd2, 0x0, 0x14, 0x0, 0x2, 0x4, 0xd2}, @@ -310,8 +310,8 @@ func TestUnmarshal(t *testing.T) { Val []TLV `oscar:"count_prefix=uint8"` }{ Val: []TLV{ - NewTLV(10, uint16(1234)), - NewTLV(20, uint16(1234)), + NewTLVBE(10, uint16(1234)), + NewTLVBE(20, uint16(1234)), }, }, given: append( @@ -347,8 +347,8 @@ func TestUnmarshal(t *testing.T) { Val []TLV `oscar:"count_prefix=uint16"` }{ Val: []TLV{ - NewTLV(10, uint16(1234)), - NewTLV(20, uint16(1234)), + NewTLVBE(10, uint16(1234)), + NewTLVBE(20, uint16(1234)), }, }, given: append( diff --git a/wire/encode_test.go b/wire/encode_test.go index 354a5259..e552c114 100644 --- a/wire/encode_test.go +++ b/wire/encode_test.go @@ -268,8 +268,8 @@ func TestMarshal(t *testing.T) { Val []TLV `oscar:"count_prefix=uint8"` }{ Val: []TLV{ - NewTLV(10, uint16(1234)), - NewTLV(20, uint16(1234)), + NewTLVBE(10, uint16(1234)), + NewTLVBE(20, uint16(1234)), }, }, want: append( @@ -283,7 +283,7 @@ func TestMarshal(t *testing.T) { Val []TLV `oscar:"count_prefix=uint8"` }{ Val: []TLV{ - NewTLV(10, uint16(1234)), + NewTLVBE(10, uint16(1234)), }, }, wantErr: io.EOF, @@ -295,8 +295,8 @@ func TestMarshal(t *testing.T) { Val []TLV `oscar:"count_prefix=uint16"` }{ Val: []TLV{ - NewTLV(10, uint16(1234)), - NewTLV(20, uint16(1234)), + NewTLVBE(10, uint16(1234)), + NewTLVBE(20, uint16(1234)), }, }, want: append( @@ -310,7 +310,7 @@ func TestMarshal(t *testing.T) { Val []TLV `oscar:"count_prefix=uint16"` }{ Val: []TLV{ - NewTLV(10, uint16(1234)), + NewTLVBE(10, uint16(1234)), }, }, wantErr: io.EOF, diff --git a/wire/snacs.go b/wire/snacs.go index babf72b4..244497d3 100644 --- a/wire/snacs.go +++ b/wire/snacs.go @@ -552,6 +552,25 @@ const ( ICBMChannelMIME uint16 = 0x03 ICBMChannelICQ uint16 = 0x04 ICBMChannelCoBrowser uint16 = 0x05 + + ICBMMsgTypePlain uint8 = 0x01 // Plain text (simple) message + ICBMMsgTypeChat uint8 = 0x02 // Chat request message + ICBMMsgTypeFileReq uint8 = 0x03 // File request / file ok message + ICBMMsgTypeUrl uint8 = 0x04 // URL message (0xFE formatted) + ICBMMsgTypeAuthReq uint8 = 0x06 // Authorization request message (0xFE formatted) + ICBMMsgTypeAuthDeny uint8 = 0x07 // Authorization denied message (0xFE formatted) + ICBMMsgTypeAuthOK uint8 = 0x08 // Authorization given message (empty) + ICBMMsgTypeServer uint8 = 0x09 // Message from OSCAR server (0xFE formatted) + ICBMMsgTypeAdded uint8 = 0x0C // "You-were-added" message (0xFE formatted) + ICBMMsgTypeWWP uint8 = 0x0D // Web pager message (0xFE formatted) + ICBMMsgTypeEExpress uint8 = 0x0E // Email express message (0xFE formatted) + ICBMMsgTypeContacts uint8 = 0x13 // Contact list message + ICBMMsgTypePlugin uint8 = 0x1A // Plugin message described by text string + ICBMMsgTypeAutoAway uint8 = 0xE8 // Auto away message + ICBMMsgTypeAutoBusy uint8 = 0xE9 // Auto occupied message + ICBMMsgTypeAutoNA uint8 = 0xEA // Auto not available message + ICBMMsgTypeAutoDND uint8 = 0xEB // Auto do not disturb message + ICBMMsgTypeAutoFFC uint8 = 0xEC // Auto free for chat message ) // ICBMCh1Fragment represents an ICBM channel 1 (instant message) message @@ -1266,6 +1285,24 @@ type SNAC_0x13_0x11_FeedbagStartCluster struct { TLVRestBlock } +type SNAC_0x13_0x18_FeedbagRequestAuthorizationToHost struct { + ScreenName string `oscar:"len_prefix=uint8"` + Reason string `oscar:"len_prefix=uint16"` + Unknown uint16 +} + +type SNAC_0x13_0x1A_FeedbagRespondAuthorizeToHost struct { + ScreenName string `oscar:"len_prefix=uint8"` + Accepted uint8 + Reason string `oscar:"len_prefix=uint16"` +} + +type SNAC_0x13_0x1B_FeedbagRespondAuthorizeToClient struct { + ScreenName string `oscar:"len_prefix=uint8"` + Accepted uint8 + Reason string `oscar:"len_prefix=uint16"` +} + // // 0x15: ICQ // @@ -1275,7 +1312,51 @@ const ( ICQDBQuery uint16 = 0x0002 ICQDBReply uint16 = 0x0003 - ICQTLVTagsMetadata uint16 = 0x01 + ICQTLVTagsMetadata uint16 = 0x0001 + ICQTLVTagsUIN uint16 = 0x0136 // User UIN (search) + ICQTLVTagsFirstName uint16 = 0x0140 // User first name + ICQTLVTagsLastName uint16 = 0x014A // User last name + ICQTLVTagsNickname uint16 = 0x0154 // User nickname + ICQTLVTagsEmail uint16 = 0x015E // User email + ICQTLVTagsAgeRangeSearch uint16 = 0x0168 // Age range to search (search) + ICQTLVTagsAge uint16 = 0x0172 // User age + ICQTLVTagsGender uint16 = 0x017C // User gender + ICQTLVTagsSpokenLanguage uint16 = 0x0186 // User spoken language + ICQTLVTagsHomeCityName uint16 = 0x0190 // User home city name + ICQTLVTagsHomeStateAbbr uint16 = 0x019A // User home state abbreviation + ICQTLVTagsHomeCountryCode uint16 = 0x01A4 // User home country code + ICQTLVTagsWorkCompanyName uint16 = 0x01AE // User work company name + ICQTLVTagsWorkDepartmentName uint16 = 0x01B8 // User work department name + ICQTLVTagsWorkPositionTitle uint16 = 0x01C2 // User work position (title) + ICQTLVTagsWorkOccupationCode uint16 = 0x01CC // User work occupation code + ICQTLVTagsAffiliationsNode uint16 = 0x01D6 // User affiliations node + ICQTLVTagsInterestsNode uint16 = 0x01EA // User interests node + ICQTLVTagsPastInfoNode uint16 = 0x01FE // User past info node + ICQTLVTagsHomepageCategoryKeywords uint16 = 0x0212 // User homepage category/keywords + ICQTLVTagsHomepageURL uint16 = 0x0213 // User homepage URL + ICQTLVTagsWhitepagesSearchKeywords uint16 = 0x0226 // Whitepages search keywords string (search) + ICQTLVTagsSearchOnlineUsersFlag uint16 = 0x0230 // Search only online users flag (search) + ICQTLVTagsBirthdayInfo uint16 = 0x023A // User birthday info (year, month, day) + ICQTLVTagsNotesText uint16 = 0x0258 // User notes (about) text + ICQTLVTagsHomeStreetAddress uint16 = 0x0262 // User home street address + ICQTLVTagsHomeZipCode uint16 = 0x026C // User home zip code + ICQTLVTagsHomePhoneNumber uint16 = 0x0276 // User home phone number + ICQTLVTagsHomeFaxNumber uint16 = 0x0280 // User home fax number + ICQTLVTagsHomeCellularPhoneNumber uint16 = 0x028A // User home cellular phone number + ICQTLVTagsWorkStreetAddress uint16 = 0x0294 // User work street address + ICQTLVTagsWorkCityName uint16 = 0x029E // User work city name + ICQTLVTagsWorkStateName uint16 = 0x02A8 // User work state name + ICQTLVTagsWorkCountryCode uint16 = 0x02B2 // User work country code + ICQTLVTagsWorkZipCode uint16 = 0x02BC // User work zip code + ICQTLVTagsWorkPhoneNumber uint16 = 0x02C6 // User work phone number + ICQTLVTagsWorkFaxNumber uint16 = 0x02D0 // User work fax number + ICQTLVTagsWorkWebpageURL uint16 = 0x02DA // User work webpage URL + ICQTLVTagsShowWebStatusPermissions uint16 = 0x02F8 // User 'show web status' permissions + ICQTLVTagsAuthorizationPermissions uint16 = 0x030C // User authorization permissions + ICQTLVTagsGMTOffset uint16 = 0x0316 // User GMT offset + ICQTLVTagsOriginallyFromCity uint16 = 0x0320 // User originally from city + ICQTLVTagsOriginallyFromState uint16 = 0x032A // User originally from state + ICQTLVTagsOriginallyFromCountryCode uint16 = 0x0334 // User originally from country (code) ICQStatusCodeOK uint8 = 0x0A ICQStatusCodeFail uint8 = 0x32 @@ -1295,33 +1376,36 @@ const ( ) const ( - ICQDBQueryMetaReqSetBasicInfo uint16 = 0x03EA - ICQDBQueryMetaReqSetWorkInfo uint16 = 0x03F3 - ICQDBQueryMetaReqSetMoreInfo uint16 = 0x03FD - ICQDBQueryMetaReqSetNotes uint16 = 0x0406 - ICQDBQueryMetaReqSetEmails uint16 = 0x040B - ICQDBQueryMetaReqSetInterests uint16 = 0x0410 - ICQDBQueryMetaReqSetAffiliations uint16 = 0x041A - ICQDBQueryMetaReqSetPermissions uint16 = 0x0424 - ICQDBQueryMetaReqShortInfo uint16 = 0x04BA - ICQDBQueryMetaReqFullInfo uint16 = 0x04B2 - ICQDBQueryMetaReqFullInfo2 uint16 = 0x04D0 - ICQDBQueryMetaReqSearchByDetails uint16 = 0x0515 - ICQDBQueryMetaReqSearchByUIN uint16 = 0x051F - ICQDBQueryMetaReqSearchByEmail uint16 = 0x0529 - ICQDBQueryMetaReqSearchWhitePages uint16 = 0x0533 - ICQDBQueryMetaReqXMLReq uint16 = 0x0898 - ICQDBQueryMetaReqStat0a8c uint16 = 0x0A8C - ICQDBQueryMetaReqStat0a96 uint16 = 0x0A96 - ICQDBQueryMetaReqStat0aaa uint16 = 0x0AAA - ICQDBQueryMetaReqStat0ab4 uint16 = 0x0AB4 - ICQDBQueryMetaReqStat0ab9 uint16 = 0x0AB9 - ICQDBQueryMetaReqStat0abe uint16 = 0x0ABE - ICQDBQueryMetaReqStat0ac8 uint16 = 0x0AC8 - ICQDBQueryMetaReqStat0acd uint16 = 0x0ACD - ICQDBQueryMetaReqStat0ad2 uint16 = 0x0AD2 - ICQDBQueryMetaReqStat0ad7 uint16 = 0x0AD7 - ICQDBQueryMetaReqStat0758 uint16 = 0x0758 + ICQDBQueryMetaReqSetBasicInfo uint16 = 0x03EA + ICQDBQueryMetaReqSetWorkInfo uint16 = 0x03F3 + ICQDBQueryMetaReqSetMoreInfo uint16 = 0x03FD + ICQDBQueryMetaReqSetNotes uint16 = 0x0406 + ICQDBQueryMetaReqSetEmails uint16 = 0x040B + ICQDBQueryMetaReqSetInterests uint16 = 0x0410 + ICQDBQueryMetaReqSetAffiliations uint16 = 0x041A + ICQDBQueryMetaReqSetPermissions uint16 = 0x0424 + ICQDBQueryMetaReqShortInfo uint16 = 0x04BA + ICQDBQueryMetaReqFullInfo uint16 = 0x04B2 + ICQDBQueryMetaReqFullInfo2 uint16 = 0x04D0 + ICQDBQueryMetaReqSearchByDetails uint16 = 0x0515 + ICQDBQueryMetaReqSearchByUIN uint16 = 0x051F + ICQDBQueryMetaReqSearchByEmail uint16 = 0x0529 + ICQDBQueryMetaReqSearchWhitePages uint16 = 0x0533 + ICQDBQueryMetaReqSearchWhitePages2 uint16 = 0x055F + ICQDBQueryMetaReqSearchByUIN2 uint16 = 0x0569 + ICQDBQueryMetaReqSearchByEmail3 uint16 = 0x0573 + ICQDBQueryMetaReqStat0758 uint16 = 0x0758 + ICQDBQueryMetaReqXMLReq uint16 = 0x0898 + ICQDBQueryMetaReqStat0a8c uint16 = 0x0A8C + ICQDBQueryMetaReqStat0a96 uint16 = 0x0A96 + ICQDBQueryMetaReqStat0aaa uint16 = 0x0AAA + ICQDBQueryMetaReqStat0ab4 uint16 = 0x0AB4 + ICQDBQueryMetaReqStat0ab9 uint16 = 0x0AB9 + ICQDBQueryMetaReqStat0abe uint16 = 0x0ABE + ICQDBQueryMetaReqStat0ac8 uint16 = 0x0AC8 + ICQDBQueryMetaReqStat0acd uint16 = 0x0ACD + ICQDBQueryMetaReqStat0ad2 uint16 = 0x0AD2 + ICQDBQueryMetaReqStat0ad7 uint16 = 0x0AD7 ICQDBQueryMetaReplySetBasicInfo uint16 = 0x0064 ICQDBQueryMetaReplySetWorkInfo uint16 = 0x006E @@ -1368,16 +1452,33 @@ type ICQ_0x07D0_0x051F_DBQueryMetaReqSearchByUIN struct { UIN uint32 } +type ICQ_0x07D0_0x0569_DBQueryMetaReqSearchByUIN2 struct { + TLVRestBlock +} + type ICQ_0x07D0_0x0529_DBQueryMetaReqSearchByEmail struct { Email string `oscar:"len_prefix=uint16,nullterm"` } +type ICQ_0x07D0_0x0573_DBQueryMetaReqSearchByEmail3 struct { + TLVRestBlock +} + type ICQ_0x07D0_0x0515_DBQueryMetaReqSearchByDetails struct { FirstName string `oscar:"len_prefix=uint16,nullterm"` LastName string `oscar:"len_prefix=uint16,nullterm"` NickName string `oscar:"len_prefix=uint16,nullterm"` } +type ICQInterests struct { + Code uint16 + Keyword string `oscar:"len_prefix=uint16,nullterm"` +} + +type ICQEmail struct { + Email string `oscar:"len_prefix=uint16,nullterm"` +} + type ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages struct { FirstName string `oscar:"len_prefix=uint16,nullterm"` LastName string `oscar:"len_prefix=uint16,nullterm"` @@ -1405,6 +1506,10 @@ type ICQ_0x07D0_0x0533_DBQueryMetaReqSearchWhitePages struct { SearchScope uint8 } +type ICQ_0x07D0_0x055F_DBQueryMetaReqSearchWhitePages2 struct { + TLVRestBlock +} + type ICQ_0x07D0_0x03FD_DBQueryMetaReqSetMoreInfo struct { Age uint8 // not used because age is calculated from birthdate Gender uint16 diff --git a/wire/tlv.go b/wire/tlv.go index 556a493d..68906e4d 100644 --- a/wire/tlv.go +++ b/wire/tlv.go @@ -14,8 +14,17 @@ type TLV struct { Value []byte `oscar:"len_prefix=uint16"` } -// NewTLV creates a new instance of TLV. -func NewTLV(tag uint16, val any) TLV { +// NewTLVBE creates a new TLV. Values are marshalled in big-endian order. +func NewTLVBE(tag uint16, val any) TLV { + return newTLV(tag, val, binary.BigEndian) +} + +// NewTLVLE creates a new TLV. Values are marshalled in little-endian order. +func NewTLVLE(tag uint16, val any) TLV { + return newTLV(tag, val, binary.LittleEndian) +} + +func newTLV(tag uint16, val any, order binary.ByteOrder) TLV { t := TLV{ Tag: tag, } @@ -23,8 +32,15 @@ func NewTLV(tag uint16, val any) TLV { t.Value = val.([]byte) } else { buf := &bytes.Buffer{} - if err := MarshalBE(val, buf); err != nil { - panic(fmt.Sprintf("unable to create TLV: %s", err.Error())) + switch order { + case binary.BigEndian: + if err := MarshalBE(val, buf); err != nil { + panic(fmt.Sprintf("unable to create TLV: %s", err.Error())) + } + case binary.LittleEndian: + if err := MarshalLE(val, buf); err != nil { + panic(fmt.Sprintf("unable to create TLV: %s", err.Error())) + } } t.Value = buf.Bytes() } @@ -67,8 +83,12 @@ func (s *TLVList) AppendList(tlvs []TLV) { *s = append(*s, tlvs...) } -// String retrieves the string value of a TLV with a tag value from the TLV -// list. It returns false if the tag does not exist in the list. +// String retrieves the string value associated with the specified tag from the +// TLVList. +// +// If the specified tag is found, the function returns the associated string +// value and true. If the tag is not found, the function returns an empty +// string and false. func (s *TLVList) String(tag uint16) (string, bool) { for _, tlv := range *s { if tag == tlv.Tag { @@ -78,9 +98,52 @@ func (s *TLVList) String(tag uint16) (string, bool) { return "", false } -// Slice retrieves the slice value of a TLV with a tag value from the TLV -// list. It returns false if the tag does not exist in the list. -func (s *TLVList) Slice(tag uint16) ([]byte, bool) { +// ICQString retrieves the ICQ string value associated with the specified tag +// from the TLVList. +// +// An ICQ string is a string that is prefixed with its length and ends with a +// null terminator. +// +// If the specified tag is found, the function returns the extracted string +// value and true. If the tag is not found or the string is malformed, the +// function returns an empty string and false. +func (s *TLVList) ICQString(tag uint16) (string, bool) { + // Find the TLV entry with the specified tag + for _, tlv := range *s { + if tag != tlv.Tag { + continue + } + + // Ensure the value is long enough to contain a valid length prefix and value + if len(tlv.Value) < 3 { + break + } + + // Extract the length prefix (first 2 bytes) as a uint16 + expectedLength := binary.LittleEndian.Uint16(tlv.Value[0:2]) + + // Extract the actual string value, excluding the length prefix + value := tlv.Value[2:] + + // Check if the length matches the value length (including the null terminator) + if int(expectedLength) != len(value) { + break + } + + // Remove the null terminator + return string(value[:len(value)-1]), true + } + + // Tag not found + return "", false +} + +// Bytes retrieves the byte payload associated with the specified tag from the +// TLVList. +// +// If the specified tag is found, the function returns the associated byte +// slice and true. If the tag is not found, the function returns nil and false. +func (s *TLVList) Bytes(tag uint16) ([]byte, bool) { for _, tlv := range *s { if tag == tlv.Tag { return tlv.Value, true @@ -89,25 +152,59 @@ func (s *TLVList) Slice(tag uint16) ([]byte, bool) { return nil, false } -// Uint16 retrieves the uint16 value of a TLV with a tag value from the TLV -// list. It returns false if the tag does not exist in the list. It may panic -// if the TLV value is not uint16. -func (s *TLVList) Uint16(tag uint16) (uint16, bool) { +// Uint16BE retrieves a 16-bit unsigned integer value from the TLVList +// associated with the specified tag, interpreting the bytes in big-endian +// format. +// +// If the specified tag is found, the function returns the associated value +// as a uint16 and true. If the tag is not found, the function returns 0 and +// false. +func (s *TLVList) Uint16BE(tag uint16) (uint16, bool) { + return s.uint16(tag, binary.BigEndian) +} + +// Uint16LE retrieves a 16-bit unsigned integer value from the TLVList +// associated with the specified tag, interpreting the bytes in little-endian +// format. +// +// If the specified tag is found, the function returns the associated value +// as a uint16 and true. If the tag is not found, the function returns 0 and +// false. +func (s *TLVList) Uint16LE(tag uint16) (uint16, bool) { + return s.uint16(tag, binary.LittleEndian) +} + +func (s *TLVList) uint16(tag uint16, order binary.ByteOrder) (uint16, bool) { for _, tlv := range *s { if tag == tlv.Tag { - return binary.BigEndian.Uint16(tlv.Value), true + return order.Uint16(tlv.Value), true } } return 0, false } -// Uint32 retrieves the uint32 value of a TLV with a tag value from the TLV -// list. It returns false if the tag does not exist in the list. It may panic -// if the TLV value is not uint32. -func (s *TLVList) Uint32(tag uint16) (uint32, bool) { +// Uint32BE retrieves a 32-bit unsigned integer value from the TLVList +// associated with the specified tag, interpreting the bytes in big-endian format. +// +// If the specified tag is found, the function returns the associated value +// as a uint32 and true. If the tag is not found, the function returns 0 and false. +func (s *TLVList) Uint32BE(tag uint16) (uint32, bool) { + return s.uint32(tag, binary.BigEndian) +} + +// Uint32LE retrieves a 32-bit unsigned integer value from the TLVList +// associated with the specified tag, interpreting the bytes in little-endian format. +// +// If the specified tag is found, the function returns the associated value +// as a uint32 and true. If the tag is not found, the function returns 0 and false. +func (s *TLVList) Uint32LE(tag uint16) (uint32, bool) { + return s.uint32(tag, binary.LittleEndian) +} + +func (s *TLVList) uint32(tag uint16, order binary.ByteOrder) (uint32, bool) { for _, tlv := range *s { if tag == tlv.Tag { - return binary.BigEndian.Uint32(tlv.Value), true + return order.Uint32(tlv.Value), true } } return 0, false diff --git a/wire/tlv_test.go b/wire/tlv_test.go index 4d1d65de..5e6f6a5c 100644 --- a/wire/tlv_test.go +++ b/wire/tlv_test.go @@ -23,9 +23,9 @@ func TestTLVList_Append(t *testing.T) { } have := TLVList{} - have.Append(NewTLV(0, []byte(`0`))) - have.Append(NewTLV(1, []byte(`1`))) - have.Append(NewTLV(2, []byte(`2`))) + have.Append(NewTLVBE(0, []byte(`0`))) + have.Append(NewTLVBE(1, []byte(`1`))) + have.Append(NewTLVBE(2, []byte(`2`))) assert.Equal(t, want, have) } @@ -48,18 +48,15 @@ func TestTLVList_AppendList(t *testing.T) { have := TLVList{} have.AppendList([]TLV{ - NewTLV(0, []byte(`0`)), - NewTLV(1, []byte(`1`)), - NewTLV(2, []byte(`2`)), + NewTLVBE(0, []byte(`0`)), + NewTLVBE(1, []byte(`1`)), + NewTLVBE(2, []byte(`2`)), }) assert.Equal(t, want, have) } func TestTLVList_Getters(t *testing.T) { - type args struct { - tType uint16 - } tests := []struct { name string given []TLV @@ -70,53 +67,105 @@ func TestTLVList_Getters(t *testing.T) { panic bool }{ { - name: "given a TLV of uint32, expect found value", + name: "given a TLV of big-endian uint32, expect found value", + given: []TLV{ + NewTLVBE(0, uint32(12)), + NewTLVBE(1, uint32(34)), + NewTLVBE(2, uint32(56)), + }, + lookup: func(l TLVList) (any, bool) { + return l.Uint32BE(1) + }, + expect: uint32(34), + found: true, + }, + { + name: "given a TLV of big-endian uint32, expect not found value", + given: []TLV{ + NewTLVBE(0, uint32(12)), + NewTLVBE(1, uint32(34)), + NewTLVBE(2, uint32(56)), + }, + lookup: func(l TLVList) (any, bool) { + return l.Uint32BE(3) + }, + expect: uint32(0), + found: false, + }, + { + name: "given a TLV of big-endian uint16, expect found value", + given: []TLV{ + NewTLVBE(0, uint16(12)), + NewTLVBE(1, uint16(34)), + NewTLVBE(2, uint16(56)), + }, + lookup: func(l TLVList) (any, bool) { + return l.Uint16BE(1) + }, + expect: uint16(34), + found: true, + }, + { + name: "given a TLV of big-endian uint16, expect not found value", + given: []TLV{ + NewTLVBE(0, uint16(12)), + NewTLVBE(1, uint16(34)), + NewTLVBE(2, uint16(56)), + }, + lookup: func(l TLVList) (any, bool) { + return l.Uint16BE(3) + }, + expect: uint16(0), + found: false, + }, + { + name: "given a TLV of little-endian uint32, expect found value", given: []TLV{ - NewTLV(0, uint32(12)), - NewTLV(1, uint32(34)), - NewTLV(2, uint32(56)), + NewTLVLE(0, uint32(12)), + NewTLVLE(1, uint32(34)), + NewTLVLE(2, uint32(56)), }, lookup: func(l TLVList) (any, bool) { - return l.Uint32(1) + return l.Uint32LE(1) }, expect: uint32(34), found: true, }, { - name: "given a TLV of uint32, expect not found value", + name: "given a TLV of little-endian uint32, expect not found value", given: []TLV{ - NewTLV(0, uint32(12)), - NewTLV(1, uint32(34)), - NewTLV(2, uint32(56)), + NewTLVLE(0, uint32(12)), + NewTLVLE(1, uint32(34)), + NewTLVLE(2, uint32(56)), }, lookup: func(l TLVList) (any, bool) { - return l.Uint32(3) + return l.Uint32LE(3) }, expect: uint32(0), found: false, }, { - name: "given a TLV of uint16, expect found value", + name: "given a TLV of little-endian uint16, expect found value", given: []TLV{ - NewTLV(0, uint16(12)), - NewTLV(1, uint16(34)), - NewTLV(2, uint16(56)), + NewTLVLE(0, uint16(12)), + NewTLVLE(1, uint16(34)), + NewTLVLE(2, uint16(56)), }, lookup: func(l TLVList) (any, bool) { - return l.Uint16(1) + return l.Uint16LE(1) }, expect: uint16(34), found: true, }, { - name: "given a TLV of uint16, expect not found value", + name: "given a TLV of little-endian uint16, expect not found value", given: []TLV{ - NewTLV(0, uint16(12)), - NewTLV(1, uint16(34)), - NewTLV(2, uint16(56)), + NewTLVLE(0, uint16(12)), + NewTLVLE(1, uint16(34)), + NewTLVLE(2, uint16(56)), }, lookup: func(l TLVList) (any, bool) { - return l.Uint16(3) + return l.Uint16LE(3) }, expect: uint16(0), found: false, @@ -124,9 +173,9 @@ func TestTLVList_Getters(t *testing.T) { { name: "given a TLV of string, expect found value", given: []TLV{ - NewTLV(0, "12"), - NewTLV(1, "34"), - NewTLV(2, "56"), + NewTLVBE(0, "12"), + NewTLVBE(1, "34"), + NewTLVBE(2, "56"), }, lookup: func(l TLVList) (any, bool) { return l.String(1) @@ -137,9 +186,9 @@ func TestTLVList_Getters(t *testing.T) { { name: "given a TLV of string, expect not found value", given: []TLV{ - NewTLV(0, "12"), - NewTLV(1, "34"), - NewTLV(2, "56"), + NewTLVBE(0, "12"), + NewTLVBE(1, "34"), + NewTLVBE(2, "56"), }, lookup: func(l TLVList) (any, bool) { return l.String(3) @@ -150,12 +199,12 @@ func TestTLVList_Getters(t *testing.T) { { name: "given a TLV of slice, expect found value", given: []TLV{ - NewTLV(0, []byte(`12`)), - NewTLV(1, []byte(`34`)), - NewTLV(2, []byte(`56`)), + NewTLVBE(0, []byte(`12`)), + NewTLVBE(1, []byte(`34`)), + NewTLVBE(2, []byte(`56`)), }, lookup: func(l TLVList) (any, bool) { - return l.Slice(1) + return l.Bytes(1) }, expect: []byte(`34`), found: true, @@ -163,25 +212,37 @@ func TestTLVList_Getters(t *testing.T) { { name: "given a TLV of string, expect not found value", given: []TLV{ - NewTLV(0, []byte(`12`)), - NewTLV(1, []byte(`34`)), - NewTLV(2, []byte(`56`)), + NewTLVBE(0, []byte(`12`)), + NewTLVBE(1, []byte(`34`)), + NewTLVBE(2, []byte(`56`)), }, lookup: func(l TLVList) (any, bool) { - return l.Slice(3) + return l.Bytes(3) }, expect: []byte(nil), found: false, }, { - name: "expect a panic when there's a type mismatch", + name: "expect a panic when there's a type mismatch between big-endian uint16 and uint32", + given: []TLV{ + NewTLVBE(0, uint16(12)), + NewTLVBE(1, uint16(34)), + NewTLVBE(2, uint16(56)), + }, + lookup: func(l TLVList) (any, bool) { + return l.Uint32BE(1) + }, + panic: true, + }, + { + name: "expect a panic when there's a type mismatch between little-endian uint16 and uint32", given: []TLV{ - NewTLV(0, uint16(12)), - NewTLV(1, uint16(34)), - NewTLV(2, uint16(56)), + NewTLVLE(0, uint16(12)), + NewTLVLE(1, uint16(34)), + NewTLVLE(2, uint16(56)), }, lookup: func(l TLVList) (any, bool) { - return l.Uint32(1) + return l.Uint32LE(1) }, panic: true, }, @@ -199,10 +260,80 @@ func TestTLVList_Getters(t *testing.T) { } } -func TestTLVList_NewTLVPanic(t *testing.T) { - // make sure NewTLV panics when it encounters an unsupported type, in this +func TestTLVList_NewTLVBEPanic(t *testing.T) { + // make sure NewTLVBE panics when it encounters an unsupported type, in this // case it's int. assert.Panics(t, func() { - NewTLV(1, 30) + NewTLVBE(1, 30) + }) +} + +func TestTLVList_NewTLVLEPanic(t *testing.T) { + // make sure NewTLVLE panics when it encounters an unsupported type, in this + // case it's int. + assert.Panics(t, func() { + NewTLVLE(1, 30) + }) +} + +func TestTLVList_ICQString(t *testing.T) { + // Create a new TLV list + tlv := TLVList{} + + // Add a valid ICQ string TLV entry to the list + tlv.Append(NewTLVLE(0x01, []byte{0x09, 0x00, 'k', 'n', 'i', 't', 't', 'i', 'n', 'g', '\x00'})) + + t.Run("Valid ICQString", func(t *testing.T) { + // Test retrieving a valid ICQ string + str, ok := tlv.ICQString(0x01) + assert.True(t, ok) + assert.Equal(t, "knitting", str) + }) + + t.Run("Non-existent Tag", func(t *testing.T) { + // Test retrieving an ICQ string for a non-existent tag + str, ok := tlv.ICQString(0x02) + assert.False(t, ok) + assert.Empty(t, str) + }) + + t.Run("Malformed ICQString", func(t *testing.T) { + // Add a malformed TLV entry (length prefix too short) + tlvMalformed := TLVList{} + tlvMalformed.Append(NewTLVLE(0x03, []byte{0x02, 0x00, 'a'})) // Length 2 but only 1 character and no null terminator + + str, ok := tlvMalformed.ICQString(0x03) + assert.False(t, ok) + assert.Empty(t, str) + }) + + t.Run("Incorrect Length Prefix", func(t *testing.T) { + // Add an incorrect length prefix (does not match actual string length) + tlvIncorrectLength := TLVList{} + tlvIncorrectLength.Append(NewTLVLE(0x04, []byte{0x0A, 0x00, 'k', 'n', 'i', 't', 't', 'i', 'n', 'g', '\x00'})) // Length prefix is 9 but actual length is 7 + 1 (null terminator) + + str, ok := tlvIncorrectLength.ICQString(0x04) + assert.False(t, ok) + assert.Empty(t, str) + }) + + t.Run("Short Length Prefix", func(t *testing.T) { + // Add a TLV with a length prefix, but the data is too short to contain a valid ICQ string + tlvShortLength := TLVList{} + tlvShortLength.Append(NewTLVLE(0x05, []byte{0x05, 0x00})) // Length prefix is 5 but no data + + str, ok := tlvShortLength.ICQString(0x05) + assert.False(t, ok) + assert.Empty(t, str) + }) + + t.Run("Empty String", func(t *testing.T) { + // Add a TLV with an empty ICQ string (just the length prefix and null terminator) + tlvEmptyString := TLVList{} + tlvEmptyString.Append(NewTLVLE(0x06, []byte{0x01, 0x00, '\x00'})) // Length prefix is 1 with just null terminator + + str, ok := tlvEmptyString.ICQString(0x06) + assert.True(t, ok) + assert.Empty(t, str) }) }