CI / build (push) Successful in 34s
The shop's T5 filter (maturity_rating "t5") is answered from the hub's products, fetched so they can be
shown and tried on; buying T5 products adds them to the hub library, and product.php details for
community products are answered here.
The client sends some product IDs as floats ("2000000008.0"): product.php passed the worn community
product to IMVU that way. Every ID is now read either way, and products.Guard refuses any request to
IMVU that still names a local ID given out. T5DE_PROXY_DUMP logs request and response bodies.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
42 lines
1.4 KiB
Go
42 lines
1.4 KiB
Go
package products
|
|
|
|
import (
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"git.t5de.dev/t5de/t5de-proxy/internal/proxy"
|
|
)
|
|
|
|
// Guard is the last check before a request goes to IMVU: one that still names a community product (a local ID the
|
|
// proxy gave out, in its query or body, as an integer or a float) is refused, not sent. The interceptors take
|
|
// community products out of every request known to carry them; Guard stops the ones not known yet, and logs them
|
|
// so they can be handled.
|
|
type Guard struct{ Products *Products }
|
|
|
|
var localIDPattern = regexp.MustCompile(`(?:^|[^0-9.])(2[0-9]{9})(?:\.0+)?(?:[^0-9.]|$)`)
|
|
|
|
func (g Guard) Intercept(x *proxy.Exchange) error {
|
|
if x.Response != nil || !strings.HasSuffix(strings.ToLower(x.URL.Hostname()), ".imvu.com") {
|
|
return nil
|
|
}
|
|
query, _ := url.QueryUnescape(x.URL.RawQuery)
|
|
for _, text := range []string{query, x.URL.Path, string(x.Body)} {
|
|
for _, m := range localIDPattern.FindAllStringSubmatch(text, -1) {
|
|
id, ok := parseID(m[1])
|
|
if ok && IsCommunity(id) && g.Products.given(id) {
|
|
g.Products.logf("products: refused a request to %s%s: it names community product %d", x.URL.Host, x.URL.Path, id)
|
|
x.Response = localResponse(403, "application/json", []byte(`{"error":"t5de: community products stay off IMVU"}`))
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// given reports whether a local ID was given to a product.
|
|
func (p *Products) given(local int64) bool {
|
|
_, ok := p.state.productID(local)
|
|
return ok
|
|
}
|