From 56c47e806fc32b82361bb12dc85f7ecf649a4191 Mon Sep 17 00:00:00 2001 From: dhkatz Date: Fri, 30 Oct 2026 07:05:25 -0700 Subject: [PATCH] Remove the hosted rooms' old owner mapping Hosted rooms' instance IDs start with their owner's IMVU account now, so the client asks about their products as the owner itself, and the mapping from 2100000000 is never used. Co-Authored-By: Claude Opus 5.5 --- cmd/t5de-proxy/main.go | 1 - internal/hosted/hosted.go | 11 --------- internal/products/decor.go | 2 +- internal/products/intercept.go | 39 +----------------------------- internal/products/products.go | 11 +++------ internal/products/products_test.go | 21 ---------------- 6 files changed, 6 insertions(+), 79 deletions(-) diff --git a/cmd/t5de-proxy/main.go b/cmd/t5de-proxy/main.go index 4901dd8..c5d380a 100644 --- a/cmd/t5de-proxy/main.go +++ b/cmd/t5de-proxy/main.go @@ -156,7 +156,6 @@ func run(logger *log.Logger, listen, ready string, parentPID int, trace bool, pa if prods != nil { prods.Hosted = rooms rooms.User, rooms.LocalProduct, rooms.GlobalProduct = prods.User, prods.LocalID, prods.ProductID - prods.HostedOwner = rooms.Owner rooms.UserDeliver = prods.DeliverToUser rooms.Deliver = func(c *proxy.IMQConn, m imq.Delivered) { m.Message = prods.Incoming(c, m) diff --git a/internal/hosted/hosted.go b/internal/hosted/hosted.go index 99a13b5..5200e8a 100644 --- a/internal/hosted/hosted.go +++ b/internal/hosted/hosted.go @@ -645,17 +645,6 @@ func (r *Rooms) getRoom(ctx context.Context, n int64) (*Room, [][3]any, string, return &out.Room, out.Scene.Contents, out.Scene.Hash, nil } -// Owner is the IMVU account owning the hosted room the client joined last (0 if none, or not known): the client -// checks the room's products against it (products.HostedOwner). -func (r *Rooms) Owner() int64 { - r.mu.Lock() - defer r.mu.Unlock() - if _, in := r.rooms[r.last]; !in { - return 0 - } - return r.owners[r.last] -} - func (r *Rooms) roomCard(ctx context.Context, n int64) *http.Response { rm, _, _, err := r.getRoom(ctx, n) if err != nil { diff --git a/internal/products/decor.go b/internal/products/decor.go index 705616d..cd01127 100644 --- a/internal/products/decor.go +++ b/internal/products/decor.go @@ -138,7 +138,7 @@ func roomOwner(instance string) int64 { func isHostedInstance(instance string) bool { _, number, ok := strings.Cut(instance, "-") n, err := strconv.ParseInt(number, 10, 64) - return ok && err == nil && n > HostedOwnerID // hosted rooms' numbers start above 2100000000 + return ok && err == nil && n > hostedBase } // decorFetch gets a room's decorations, from memory or the hub. diff --git a/internal/products/intercept.go b/internal/products/intercept.go index 1aa272f..0564b57 100644 --- a/internal/products/intercept.go +++ b/internal/products/intercept.go @@ -367,13 +367,6 @@ func (p *Products) authorizeProducts2(x *proxy.Exchange, call *xmlrpc.Call) erro type auth struct { user, product int64 } - // In a room hosted by T5DE's hub, the client asks about the room's products as user 2100000000 (the first part - // of the room's ID): IMVU is asked about the room owner's instead, and answers go back as 2100000000. - owner := int64(0) - if p.HostedOwner != nil { - owner = p.HostedOwner() - } - hostedAsked := map[int64]bool{} var community []auth forward := []xmlrpc.Value{table[0]} asked := map[auth]bool{} @@ -387,10 +380,6 @@ func (p *Products) authorizeProducts2(x *proxy.Exchange, call *xmlrpc.Call) erro if !ok1 || !ok2 { return nil } - if user == HostedOwnerID && owner > 0 { - user, hostedAsked[product] = owner, true - row = []xmlrpc.Value{user, product} - } if !IsCommunity(product) { if !asked[auth{user, product}] { forward, asked[auth{user, product}] = append(forward, row), true @@ -405,33 +394,9 @@ func (p *Products) authorizeProducts2(x *proxy.Exchange, call *xmlrpc.Call) erro } } } - if len(community) == 0 && len(hostedAsked) == 0 { + if len(community) == 0 { return nil } - // hostedBack gives rows asked about as 2100000000 that user ID back. - hostedBack := func(columns []xmlrpc.Value, rows []xmlrpc.Value) { - userCol, productCol := -1, -1 - for i, c := range columns { - switch c { - case "userId": - userCol = i - case "productId": - productCol = i - } - } - if userCol < 0 || productCol < 0 { - return - } - for _, row := range rows { - r, ok := row.([]xmlrpc.Value) - if !ok || len(r) <= userCol || len(r) <= productCol { - continue - } - if product, _ := r[productCol].(int64); r[userCol] == owner && hostedAsked[product] { - r[userCol] = int64(HostedOwnerID) - } - } - } ours := func(columns []xmlrpc.Value) []xmlrpc.Value { var rows []xmlrpc.Value for _, a := range community { @@ -464,7 +429,6 @@ func (p *Products) authorizeProducts2(x *proxy.Exchange, call *xmlrpc.Call) erro columns[i] = c } out := append([]xmlrpc.Value{columns}, ours(columns)...) - hostedBack(columns, out[1:]) x.Response = localResponse(200, "text/xml", (&xmlrpc.Response{Params: []xmlrpc.Value{out}}).Marshal()) return nil } @@ -492,7 +456,6 @@ func (p *Products) authorizeProducts2(x *proxy.Exchange, call *xmlrpc.Call) erro return body, errors.New("products: unexpected authorizeProducts2 columns") } all := append(rows, ours(columns)...) - hostedBack(columns, all[1:]) r.Params[0] = all return r.Marshal(), nil } diff --git a/internal/products/products.go b/internal/products/products.go index f998f1b..cbed88e 100644 --- a/internal/products/products.go +++ b/internal/products/products.go @@ -73,10 +73,8 @@ type Products struct { SaveDecorations func(ctx context.Context, instance string, items []DecorItem) error decor decorations - // Hosted, if set, serves T5DE-hosted rooms' queues (the hosted package); HostedOwner is the IMVU account owning - // the hosted room the client is in (0 if none), whose products the room's are. - Hosted HostedRooms - HostedOwner func() int64 + // Hosted, if set, serves T5DE-hosted rooms' queues (the hosted package). + Hosted HostedRooms roomMu sync.Mutex room room @@ -110,9 +108,8 @@ func (p *Products) Ready(id string) { } } -// HostedOwnerID is the user ID the client gives hosted rooms' owner: the first part of their instance IDs -// (hosted.Base). -const HostedOwnerID = 2100000000 +// hostedBase is where hosted rooms' numbers start (above it; hosted.Base). +const hostedBase = 2100000000 // HostedRooms serves T5DE-hosted rooms' IMQ queues: Route answers subscriptions to them, Send takes the client's // messages to them (message as for others, original as the client sent it, for the echo; keep: nothing to send diff --git a/internal/products/products_test.go b/internal/products/products_test.go index 5a8f279..1cb8fbe 100644 --- a/internal/products/products_test.go +++ b/internal/products/products_test.go @@ -425,24 +425,3 @@ func TestSavedOutfits(t *testing.T) { t.Fatalf("outfits %s", body) } } - -func TestHostedRoomProducts(t *testing.T) { - h, _ := newHarness(t) - h.do("POST", "https://secure.imvu.com/api/xmlrpc/client.php", call("test.avatarInfoForLogin2"), false, false) - h.p.HostedOwner = func() int64 { return 7 } // the fake IMVU answers as user 7 - auths := xmlrpc.Struct{{Name: "auths", Value: []xmlrpc.Value{ - []xmlrpc.Value{"userId", "productId"}, []xmlrpc.Value{int64(HostedOwnerID), int64(500)}}}} - _, body := h.do("POST", "http://client-dynamic.imvu.com/api/xmlrpc/client.php", call("test.authorizeProducts2", auths), true, false) - asked := h.imvu.asked["test.authorizeProducts2"] - if len(asked) != 1 || strings.Contains(asked[0], "2100000000") { - t.Fatalf("IMVU was asked %q", asked) - } - r, err := xmlrpc.ParseResponse(body) - if err != nil { - t.Fatal(err) - } - rows := r.Params[0].([]xmlrpc.Value) - if first := rows[1].([]xmlrpc.Value); first[0] != int64(HostedOwnerID) || first[2] != int64(500) { - t.Fatalf("answer %v", rows) - } -}