diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index d8373fd4c57..f9db48b54cf 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -16,3 +16,6 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ # [Optional] Uncomment this line to install global node packages. # RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g " 2>&1 + +RUN addgroup --system --gid 2001 prebidgroup && adduser --system --uid 1001 --ingroup prebidgroup prebid +USER prebid \ No newline at end of file diff --git a/.github/workflows/scripts/codepath-notification b/.github/workflows/scripts/codepath-notification index c59eaf2e41c..2c1bb0fb9be 100644 --- a/.github/workflows/scripts/codepath-notification +++ b/.github/workflows/scripts/codepath-notification @@ -13,3 +13,7 @@ # The aim is to find a minimal set of regex patterns that matches any file in these paths rubicon: header-bidding@magnite.com +pubmatic: header-bidding@pubmatic.com +openx: prebid@openx.com +adapters/ix|imp_ix|ix.json|ix.yaml: pdu-supply-prebid@indexexchange.com +medianet: prebid@media.net diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 09a0fd56791..d3831d8044f 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -11,7 +11,7 @@ on: jobs: build: name: Trivy - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 diff --git a/.github/workflows/validate-merge.yml b/.github/workflows/validate-merge.yml index 729a17114e1..ca633d47465 100644 --- a/.github/workflows/validate-merge.yml +++ b/.github/workflows/validate-merge.yml @@ -6,7 +6,7 @@ on: jobs: validate-merge: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Install Go diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 3c1e3fac4ea..df71d61612a 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: go-version: [1.23.x, 1.24.x] - os: [ubuntu-20.04] + os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: diff --git a/Dockerfile b/Dockerfile index c2e8e4d9cf8..fe7cec5e169 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -FROM ubuntu:20.04 AS build +FROM ubuntu:22.04 AS build RUN apt-get update && \ apt-get -y upgrade && \ - apt-get install -y wget + apt-get install -y --no-install-recommends wget ca-certificates WORKDIR /tmp RUN wget https://dl.google.com/go/go1.24.0.linux-amd64.tar.gz && \ tar -xf go1.24.0.linux-amd64.tar.gz && \ @@ -14,7 +14,7 @@ ENV GOPROXY="https://proxy.golang.org" # Installing gcc as cgo uses it to build native code of some modules RUN apt-get update && \ - apt-get install -y git gcc && \ + apt-get install -y --no-install-recommends git gcc build-essential && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # CGO must be enabled because some modules depend on native C code @@ -26,7 +26,7 @@ ARG TEST="true" RUN if [ "$TEST" != "false" ]; then ./validate.sh ; fi RUN go build -mod=vendor -ldflags "-X github.com/prebid/prebid-server/v3/version.Ver=`git describe --tags | sed 's/^v//'` -X github.com/prebid/prebid-server/v3/version.Rev=`git rev-parse HEAD`" . -FROM ubuntu:20.04 AS release +FROM ubuntu:22.04 AS release LABEL maintainer="hans.hjort@xandr.com" WORKDIR /usr/local/bin/ COPY --from=build /app/prebid-server . @@ -37,10 +37,10 @@ RUN chmod -R a+r static/ stored_requests/data # Installing libatomic1 as it is a runtime dependency for some modules RUN apt-get update && \ - apt-get install -y ca-certificates mtr libatomic1 && \ + apt-get install -y --no-install-recommends ca-certificates mtr libatomic1 && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN adduser prebid_user -USER prebid_user +RUN addgroup --system --gid 2001 prebidgroup && adduser --system --uid 1001 --ingroup prebidgroup prebid +USER prebid EXPOSE 8000 EXPOSE 6060 ENTRYPOINT ["/usr/local/bin/prebid-server"] diff --git a/adapters/adnuntius/adnuntius.go b/adapters/adnuntius/adnuntius.go index 53736627d90..c1a929a7846 100644 --- a/adapters/adnuntius/adnuntius.go +++ b/adapters/adnuntius/adnuntius.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" "net/http" - "net/url" + "strconv" "strings" @@ -18,80 +18,6 @@ import ( "github.com/prebid/prebid-server/v3/util/timeutil" ) -type QueryString map[string]string -type adapter struct { - time timeutil.Time - endpoint string - extraInfo string -} -type adnAdunit struct { - AuId string `json:"auId"` - TargetId string `json:"targetId"` - Dimensions [][]int64 `json:"dimensions,omitempty"` - MaxDeals int `json:"maxDeals,omitempty"` -} - -type extDeviceAdnuntius struct { - NoCookies bool `json:"noCookies,omitempty"` -} -type siteExt struct { - Data interface{} `json:"data"` -} - -type adnAdvertiser struct { - LegalName string `json:"legalName,omitempty"` - Name string `json:"name,omitempty"` -} - -type Ad struct { - Bid struct { - Amount float64 - Currency string - } - NetBid struct { - Amount float64 - } - GrossBid struct { - Amount float64 - } - DealID string `json:"dealId,omitempty"` - AdId string - CreativeWidth string - CreativeHeight string - CreativeId string - LineItemId string - Html string - DestinationUrls map[string]string - AdvertiserDomains []string - Advertiser adnAdvertiser `json:"advertiser,omitempty"` -} - -type AdUnit struct { - AuId string - TargetId string - Html string - ResponseId string - Ads []Ad - Deals []Ad `json:"deals,omitempty"` -} - -type AdnResponse struct { - AdUnits []AdUnit -} -type adnMetaData struct { - Usi string `json:"usi,omitempty"` -} -type adnRequest struct { - AdUnits []adnAdunit `json:"adUnits"` - MetaData adnMetaData `json:"metaData,omitempty"` - Context string `json:"context,omitempty"` - KeyValues interface{} `json:"kv,omitempty"` -} - -type RequestExt struct { - Bidder adnAdunit `json:"bidder"` -} - const defaultNetwork = "default" const defaultSite = "unknown" const minutesInHour = 60 @@ -111,106 +37,13 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E return a.generateRequests(*request) } -func setHeaders(ortbRequest openrtb2.BidRequest) http.Header { - - headers := http.Header{} - headers.Add("Content-Type", "application/json;charset=utf-8") - headers.Add("Accept", "application/json") - if ortbRequest.Device != nil { - if ortbRequest.Device.IP != "" { - headers.Add("X-Forwarded-For", ortbRequest.Device.IP) - } - if ortbRequest.Device.UA != "" { - headers.Add("user-agent", ortbRequest.Device.UA) - } - } - return headers -} - -func makeEndpointUrl(ortbRequest openrtb2.BidRequest, a *adapter, noCookies bool) (string, []error) { - uri, err := url.Parse(a.endpoint) - endpointUrl := a.endpoint - if err != nil { - return "", []error{fmt.Errorf("failed to parse Adnuntius endpoint: %v", err)} - } - - gdpr, consent, err := getGDPR(&ortbRequest) - if err != nil { - return "", []error{fmt.Errorf("failed to parse Adnuntius endpoint: %v", err)} - } - - if !noCookies { - var deviceExt extDeviceAdnuntius - if ortbRequest.Device != nil && ortbRequest.Device.Ext != nil { - if err := jsonutil.Unmarshal(ortbRequest.Device.Ext, &deviceExt); err != nil { - return "", []error{fmt.Errorf("failed to parse Adnuntius endpoint: %v", err)} - } - } - - if deviceExt.NoCookies { - noCookies = true - } - } - - _, offset := a.time.Now().Zone() - tzo := -offset / minutesInHour - - q := uri.Query() - if gdpr != "" { - endpointUrl = a.extraInfo - q.Set("gdpr", gdpr) - } - - if consent != "" { - q.Set("consentString", consent) - } - - if noCookies { - q.Set("noCookies", "true") - } - - q.Set("tzo", fmt.Sprint(tzo)) - q.Set("format", "prebidServer") - - url := endpointUrl + "?" + q.Encode() - return url, nil -} - -func getImpSizes(imp openrtb2.Imp) [][]int64 { - - if len(imp.Banner.Format) > 0 { - sizes := make([][]int64, len(imp.Banner.Format)) - for i, format := range imp.Banner.Format { - sizes[i] = []int64{format.W, format.H} - } - - return sizes - } - - if imp.Banner.W != nil && imp.Banner.H != nil { - size := make([][]int64, 1) - size[0] = []int64{*imp.Banner.W, *imp.Banner.H} - return size - } - - return nil -} - -/* -Generate the requests to Adnuntius to reduce the amount of requests going out. -*/ func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters.RequestData, []error) { var requestData []*adapters.RequestData - networkAdunitMap := make(map[string][]adnAdunit) + networkAdunitMap := make(map[string][]adnRequestAdunit) headers := setHeaders(ortbRequest) var noCookies bool = false for _, imp := range ortbRequest.Imp { - if imp.Banner == nil { - return nil, []error{&errortypes.BadInput{ - Message: fmt.Sprintf("ignoring imp id=%s, Adnuntius supports only Banner", imp.ID), - }} - } var bidderExt adapters.ExtImpBidder if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { @@ -218,7 +51,6 @@ func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters Message: fmt.Sprintf("Error unmarshalling ExtImpBidder: %s", err.Error()), }} } - var adnuntiusExt openrtb_ext.ImpExtAdnunitus if err := jsonutil.Unmarshal(bidderExt.Bidder, &adnuntiusExt); err != nil { return nil, []error{&errortypes.BadInput{ @@ -235,17 +67,39 @@ func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters network = adnuntiusExt.Network } - adUnit := adnAdunit{ - AuId: adnuntiusExt.Auid, - TargetId: fmt.Sprintf("%s-%s", adnuntiusExt.Auid, imp.ID), - Dimensions: getImpSizes(imp), + // Remove when we support video. + if imp.Video != nil { + return nil, []error{&errortypes.BadInput{ + Message: fmt.Sprintf("ignoring imp id=%s, Adnuntius supports only native and banner", imp.ID), + }} + } + + if imp.Banner != nil { + adUnit := generateAdUnit(imp, adnuntiusExt, "banner") + adUnit.AdType = "" + + networkAdunitMap[network] = append( + networkAdunitMap[network], + adUnit) } - if adnuntiusExt.MaxDeals > 0 { - adUnit.MaxDeals = adnuntiusExt.MaxDeals + + if imp.Native != nil { + adUnit := generateAdUnit(imp, adnuntiusExt, "native") + adUnit.AdType = "NATIVE" + nativeRequest := json.RawMessage{} + + if err := jsonutil.Unmarshal([]byte(imp.Native.Request), &nativeRequest); err != nil { + return nil, []error{&errortypes.BadInput{ + Message: fmt.Sprintf("Error unmarshalling Native: %s", err.Error()), + }} + } + + adUnit.NativeRequest.Ortb = nativeRequest + networkAdunitMap[network] = append( + networkAdunitMap[network], + adUnit) } - networkAdunitMap[network] = append( - networkAdunitMap[network], - adUnit) + } endpoint, err := makeEndpointUrl(ortbRequest, a, noCookies) @@ -260,11 +114,18 @@ func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters site = ortbRequest.Site.Page } - extSite, erro := getSiteExtAsKv(&ortbRequest) - if erro != nil { + extSite, err := getSiteExtAsKv(&ortbRequest) + if err != nil { return nil, []error{fmt.Errorf("failed to parse site Ext: %v", err)} } + var extUser openrtb_ext.ExtUser + if ortbRequest.User != nil && ortbRequest.User.Ext != nil { + if err := jsonutil.Unmarshal(ortbRequest.User.Ext, &extUser); err != nil { + return nil, []error{fmt.Errorf("failed to parse Ext User: %v", err)} + } + } + for _, networkAdunits := range networkAdunitMap { adnuntiusRequest := adnRequest{ @@ -273,13 +134,6 @@ func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters KeyValues: extSite.Data, } - var extUser openrtb_ext.ExtUser - if ortbRequest.User != nil && ortbRequest.User.Ext != nil { - if err := jsonutil.Unmarshal(ortbRequest.User.Ext, &extUser); err != nil { - return nil, []error{fmt.Errorf("failed to parse Ext User: %v", err)} - } - } - // Will change when our adserver can accept multiple user IDS if extUser.Eids != nil && len(extUser.Eids) > 0 { if len(extUser.Eids[0].UIDs) > 0 { @@ -316,7 +170,6 @@ func (a *adapter) generateRequests(ortbRequest openrtb2.BidRequest) ([]*adapters } func (a *adapter) MakeBids(request *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { - if response.StatusCode == http.StatusBadRequest { return nil, []error{&errortypes.BadInput{ Message: fmt.Sprintf("Status code: %d, Request malformed", response.StatusCode), @@ -342,107 +195,127 @@ func (a *adapter) MakeBids(request *openrtb2.BidRequest, externalRequest *adapte return bidResponse, nil } -func getSiteExtAsKv(request *openrtb2.BidRequest) (siteExt, error) { - var extSite siteExt - if request.Site != nil && request.Site.Ext != nil { - if err := jsonutil.Unmarshal(request.Site.Ext, &extSite); err != nil { - return extSite, fmt.Errorf("failed to parse ExtSite in Adnuntius: %v", err) +func generateBidResponse(adnResponse *AdnResponse, request *openrtb2.BidRequest) (*adapters.BidderResponse, []error) { + bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(adnResponse.AdUnits)) + var currency string + adunitMap := map[string]AdUnit{} + adunitMediaTypeMap := map[string][]AdUnit{} + + /* Check the ad unit response to see if there are any multi ad */ + for _, adnRespAdunit := range adnResponse.AdUnits { + result := strings.Split(adnRespAdunit.TargetId, ":") + if adnRespAdunit.MatchedAdCount > 0 { + adunitMediaTypeMap[result[0]] = append(adunitMediaTypeMap[result[0]], adnRespAdunit) } } - return extSite, nil -} -func getGDPR(request *openrtb2.BidRequest) (string, string, error) { - - gdpr := "" - var extRegs openrtb_ext.ExtRegs - if request.Regs != nil && request.Regs.Ext != nil { - if err := jsonutil.Unmarshal(request.Regs.Ext, &extRegs); err != nil { - return "", "", fmt.Errorf("failed to parse ExtRegs in Adnuntius GDPR check: %v", err) - } - if extRegs.GDPR != nil && (*extRegs.GDPR == 0 || *extRegs.GDPR == 1) { - gdpr = strconv.Itoa(int(*extRegs.GDPR)) + /* Compare price if there are multiple media types */ + for targetId, mappedAdunit := range adunitMediaTypeMap { + highestBidAtIndex := 0 + if len(mappedAdunit) > 1 { + for index := range mappedAdunit { + if mappedAdunit[index].Ads[0].Bid.Amount > mappedAdunit[highestBidAtIndex].Ads[0].Bid.Amount { + highestBidAtIndex = index + } + } } + adunitMap[targetId] = mappedAdunit[highestBidAtIndex] } - consent := "" - if request.User != nil && request.User.Ext != nil { - var extUser openrtb_ext.ExtUser - if err := jsonutil.Unmarshal(request.User.Ext, &extUser); err != nil { - return "", "", fmt.Errorf("failed to parse ExtUser in Adnuntius GDPR check: %v", err) + for _, imp := range request.Imp { + + auId, _, _, err := jsonparser.Get(imp.Ext, "bidder", "auId") + if err != nil { + return nil, []error{&errortypes.BadInput{ + Message: fmt.Sprintf("Error at Bidder auId: %s", err.Error()), + }} } - consent = extUser.Consent - } - return gdpr, consent, nil -} + targetID := fmt.Sprintf("%s-%s", string(auId), imp.ID) -func generateReturnExt(ad Ad, request *openrtb2.BidRequest) (json.RawMessage, error) { - // We always force the publisher to render - var adRender int8 = 0 + adunit := adunitMap[targetID] - var requestRegsExt *openrtb_ext.ExtRegs - if request.Regs != nil && request.Regs.Ext != nil { - if err := jsonutil.Unmarshal(request.Regs.Ext, &requestRegsExt); err != nil { + if len(adunit.Ads) > 0 { - return nil, fmt.Errorf("Failed to parse Ext information in Adnuntius: %v", err) - } - } + ad := adunit.Ads[0] + html := adunit.Html + var mType openrtb2.MarkupType = openrtb2.MarkupBanner + var native []byte - if ad.Advertiser.Name != "" && requestRegsExt != nil && requestRegsExt.DSA != nil { - legalName := ad.Advertiser.Name - if ad.Advertiser.LegalName != "" { - legalName = ad.Advertiser.LegalName - } - ext := &openrtb_ext.ExtBid{ - DSA: &openrtb_ext.ExtBidDSA{ - AdRender: &adRender, - Paid: legalName, - Behalf: legalName, - }, - } - returnExt, err := json.Marshal(ext) - if err != nil { - return nil, fmt.Errorf("Failed to parse Ext information in Adnuntius: %v", err) - } + currency = ad.Bid.Currency + if adunit.NativeJson != nil { + nativeJson, _, _, nativeErr := jsonparser.Get(adunit.NativeJson, "ortb") + if nativeErr != nil { + return nil, []error{&errortypes.BadServerResponse{ + Message: fmt.Sprintf("Failed to parse native json where imp id=%s", imp.ID), + }} + } + native = nativeJson + } + + if native != nil { + html = string(native) + mType = openrtb2.MarkupNative + } + + adBid, err := generateAdResponse(ad, imp, html, mType, request) + if err != nil { + return nil, err + } - return returnExt, nil + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: adBid, + BidType: convertMarkupTypeToBidType(mType), + }) + + for _, deal := range adunit.Deals { + mType = 1 + dealBid, err := generateAdResponse(deal, imp, deal.Html, mType, request) + if err != nil { + return nil, err + } + + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: dealBid, + BidType: convertMarkupTypeToBidType(mType), + }) + } + } } - return nil, nil + bidResponse.Currency = currency + return bidResponse, nil } -func generateAdResponse(ad Ad, imp openrtb2.Imp, html string, request *openrtb2.BidRequest) (*openrtb2.Bid, []error) { - +func generateAdResponse(ad Ad, imp openrtb2.Imp, html string, mType openrtb2.MarkupType, request *openrtb2.BidRequest) (*openrtb2.Bid, []error) { creativeWidth, widthErr := strconv.ParseInt(ad.CreativeWidth, 10, 64) if widthErr != nil { - return nil, []error{&errortypes.BadInput{ + return nil, []error{&errortypes.BadServerResponse{ Message: fmt.Sprintf("Value of width: %s is not a string", ad.CreativeWidth), }} } creativeHeight, heightErr := strconv.ParseInt(ad.CreativeHeight, 10, 64) if heightErr != nil { - return nil, []error{&errortypes.BadInput{ + return nil, []error{&errortypes.BadServerResponse{ Message: fmt.Sprintf("Value of height: %s is not a string", ad.CreativeHeight), }} } - price := ad.Bid.Amount - var bidderExt adapters.ExtImpBidder if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { - return nil, []error{&errortypes.BadInput{ + return nil, []error{&errortypes.BadServerResponse{ Message: fmt.Sprintf("Error unmarshalling ExtImpBidder: %s", err.Error()), }} } var adnuntiusExt openrtb_ext.ImpExtAdnunitus if err := jsonutil.Unmarshal(bidderExt.Bidder, &adnuntiusExt); err != nil { - return nil, []error{&errortypes.BadInput{ + return nil, []error{&errortypes.BadServerResponse{ Message: fmt.Sprintf("Error unmarshalling ExtImpValues: %s", err.Error()), }} } + price := ad.Bid.Amount if adnuntiusExt.BidType != "" { if strings.EqualFold(string(adnuntiusExt.BidType), "net") { price = ad.NetBid.Amount @@ -454,7 +327,7 @@ func generateAdResponse(ad Ad, imp openrtb2.Imp, html string, request *openrtb2. extJson, err := generateReturnExt(ad, request) if err != nil { - return nil, []error{&errortypes.BadInput{ + return nil, []error{&errortypes.BadServerResponse{ Message: fmt.Sprintf("Error extracting Ext: %s", err.Error()), }} } @@ -470,68 +343,10 @@ func generateAdResponse(ad Ad, imp openrtb2.Imp, html string, request *openrtb2. CrID: ad.CreativeId, Price: price * 1000, AdM: html, + MType: mType, ADomain: ad.AdvertiserDomains, Ext: extJson, } - return &bid, nil - -} - -func generateBidResponse(adnResponse *AdnResponse, request *openrtb2.BidRequest) (*adapters.BidderResponse, []error) { - bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(adnResponse.AdUnits)) - var currency string - adunitMap := map[string]AdUnit{} - - for _, adnRespAdunit := range adnResponse.AdUnits { - adunitMap[adnRespAdunit.TargetId] = adnRespAdunit - } - - for _, imp := range request.Imp { - - auId, _, _, err := jsonparser.Get(imp.Ext, "bidder", "auId") - if err != nil { - return nil, []error{&errortypes.BadInput{ - Message: fmt.Sprintf("Error at Bidder auId: %s", err.Error()), - }} - } - - targetID := fmt.Sprintf("%s-%s", string(auId), imp.ID) - adunit := adunitMap[targetID] - - if len(adunit.Ads) > 0 { - - ad := adunit.Ads[0] - currency = ad.Bid.Currency - adBid, err := generateAdResponse(ad, imp, adunit.Html, request) - if err != nil { - return nil, []error{&errortypes.BadInput{ - Message: "Error at ad generation", - }} - } - - bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ - Bid: adBid, - BidType: "banner", - }) - - for _, deal := range adunit.Deals { - dealBid, err := generateAdResponse(deal, imp, deal.Html, request) - if err != nil { - return nil, []error{&errortypes.BadInput{ - Message: "Error at ad generation", - }} - } - - bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ - Bid: dealBid, - BidType: "banner", - }) - } - - } - - } - bidResponse.Currency = currency - return bidResponse, nil + return &bid, nil } diff --git a/adapters/adnuntius/adnuntius_types.go b/adapters/adnuntius/adnuntius_types.go new file mode 100644 index 00000000000..17d81cd6a03 --- /dev/null +++ b/adapters/adnuntius/adnuntius_types.go @@ -0,0 +1,86 @@ +package adnuntius + +import ( + "encoding/json" + + "github.com/prebid/prebid-server/v3/util/timeutil" +) + +type QueryString map[string]string +type adapter struct { + time timeutil.Time + endpoint string + extraInfo string +} + +type NativeRequest struct { + Ortb json.RawMessage `json:"ortb,omitempty"` +} + +type adnRequestAdunit struct { + AuId string `json:"auId"` + TargetId string `json:"targetId"` + AdType string `json:"adType,omitempty"` + NativeRequest NativeRequest `json:"nativeRequest,omitempty"` + Dimensions [][]int64 `json:"dimensions,omitempty"` + MaxDeals int `json:"maxDeals,omitempty"` +} + +type extDeviceAdnuntius struct { + NoCookies bool `json:"noCookies,omitempty"` +} +type siteExt struct { + Data interface{} `json:"data"` +} + +type adnAdvertiser struct { + LegalName string `json:"legalName,omitempty"` + Name string `json:"name,omitempty"` +} + +type Ad struct { + Bid struct { + Amount float64 + Currency string + } + NetBid struct { + Amount float64 + } + GrossBid struct { + Amount float64 + } + DealID string `json:"dealId,omitempty"` + AdId string + CreativeWidth string + CreativeHeight string + CreativeId string + LineItemId string + Html string + DestinationUrls map[string]string + AdvertiserDomains []string + Advertiser adnAdvertiser `json:"advertiser,omitempty"` +} + +type AdUnit struct { + AuId string + TargetId string + Html string + MatchedAdCount int + ResponseId string + NativeJson json.RawMessage `json:"nativeJson,omitempty"` + Ads []Ad + Deals []Ad `json:"deals,omitempty"` +} + +type AdnResponse struct { + AdUnits []AdUnit +} +type adnMetaData struct { + Usi string `json:"usi,omitempty"` +} +type adnRequest struct { + AdUnits []adnRequestAdunit `json:"adUnits"` + MetaData adnMetaData `json:"metaData,omitempty"` + Context string `json:"context,omitempty"` + KeyValues interface{} `json:"kv,omitempty"` +} diff --git a/adapters/adnuntius/adnuntius_utils.go b/adapters/adnuntius/adnuntius_utils.go new file mode 100644 index 00000000000..ebbd7a80055 --- /dev/null +++ b/adapters/adnuntius/adnuntius_utils.go @@ -0,0 +1,205 @@ +package adnuntius + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" + "strconv" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" +) + +type RequestExt struct { + Bidder adnRequestAdunit `json:"bidder"` +} + +func setHeaders(ortbRequest openrtb2.BidRequest) http.Header { + + headers := http.Header{} + headers.Add("Content-Type", "application/json;charset=utf-8") + headers.Add("Accept", "application/json") + if ortbRequest.Device != nil { + if ortbRequest.Device.IP != "" { + headers.Add("X-Forwarded-For", ortbRequest.Device.IP) + } + if ortbRequest.Device.UA != "" { + headers.Add("user-agent", ortbRequest.Device.UA) + } + } + return headers +} + +func makeEndpointUrl(ortbRequest openrtb2.BidRequest, a *adapter, noCookies bool) (string, []error) { + uri, err := url.Parse(a.endpoint) + if err != nil { + return "", []error{fmt.Errorf("failed to parse Adnuntius endpoint: %v", err)} + } + + gdpr, consent, err := getGDPR(&ortbRequest) + if err != nil { + return "", []error{fmt.Errorf("failed to parse GDPR information: %v", err)} + } + + if gdpr != "" { + extraInfoURI, err := url.Parse(a.extraInfo) + if err != nil { + return "", []error{fmt.Errorf("invalid extraInfo URL: %v", err)} + } + uri = extraInfoURI + } + + if !noCookies { + var deviceExt extDeviceAdnuntius + if ortbRequest.Device != nil && ortbRequest.Device.Ext != nil { + if err := jsonutil.Unmarshal(ortbRequest.Device.Ext, &deviceExt); err != nil { + return "", []error{fmt.Errorf("failed to parse device ext: %v", err)} + } + } + + if deviceExt.NoCookies { + noCookies = true + } + } + + _, offset := a.time.Now().Zone() + tzo := -offset / minutesInHour + + q := uri.Query() + if gdpr != "" { + q.Set("gdpr", gdpr) + } + + if consent != "" { + q.Set("consentString", consent) + } + + if noCookies { + q.Set("noCookies", "true") + } + + q.Set("tzo", strconv.Itoa(tzo)) + q.Set("format", "prebidServer") + + // Set the query params to the URI + uri.RawQuery = q.Encode() + + // Return the correctly formatted URL + return uri.String(), nil +} + +func getImpSizes(imp openrtb2.Imp, bidType string) [][]int64 { + if bidType == "banner" { + if imp.Banner != nil { + if len(imp.Banner.Format) > 0 { + sizes := make([][]int64, len(imp.Banner.Format)) + for i, format := range imp.Banner.Format { + sizes[i] = []int64{format.W, format.H} + } + + return sizes + } else if imp.Banner.W != nil && imp.Banner.H != nil { + size := make([][]int64, 1) + size[0] = []int64{*imp.Banner.W, *imp.Banner.H} + return size + } + } + } + + return nil +} + +func getSiteExtAsKv(request *openrtb2.BidRequest) (siteExt, []error) { + var extSite siteExt + if request.Site != nil && request.Site.Ext != nil { + if err := jsonutil.Unmarshal(request.Site.Ext, &extSite); err != nil { + return extSite, []error{fmt.Errorf("failed to parse site ext in Adnuntius: %v", err)} + } + } + return extSite, nil +} + +func getGDPR(request *openrtb2.BidRequest) (string, string, error) { + + gdpr := "" + var extRegs openrtb_ext.ExtRegs + if request.Regs != nil && request.Regs.Ext != nil { + if err := jsonutil.Unmarshal(request.Regs.Ext, &extRegs); err != nil { + return "", "", fmt.Errorf("failed to parse ExtRegs in Adnuntius GDPR check: %v", err) + } + if extRegs.GDPR != nil && (*extRegs.GDPR == 0 || *extRegs.GDPR == 1) { + gdpr = strconv.Itoa(int(*extRegs.GDPR)) + } + } + + consent := "" + if request.User != nil && request.User.Ext != nil { + var extUser openrtb_ext.ExtUser + if err := jsonutil.Unmarshal(request.User.Ext, &extUser); err != nil { + return "", "", fmt.Errorf("failed to parse ExtUser in Adnuntius GDPR check: %v", err) + } + consent = extUser.Consent + } + + return gdpr, consent, nil +} + +func generateReturnExt(ad Ad, request *openrtb2.BidRequest) (json.RawMessage, error) { + // We always force the publisher to render + var adRender int8 = 0 + + var requestRegsExt *openrtb_ext.ExtRegs + if request.Regs != nil && request.Regs.Ext != nil { + if err := jsonutil.Unmarshal(request.Regs.Ext, &requestRegsExt); err != nil { + + return nil, fmt.Errorf("Failed to parse Ext information in Adnuntius: %v", err) + } + } + + if ad.Advertiser.Name != "" && requestRegsExt != nil && requestRegsExt.DSA != nil { + legalName := ad.Advertiser.Name + if ad.Advertiser.LegalName != "" { + legalName = ad.Advertiser.LegalName + } + ext := &openrtb_ext.ExtBid{ + DSA: &openrtb_ext.ExtBidDSA{ + AdRender: &adRender, + Paid: legalName, + Behalf: legalName, + }, + } + + returnExt, err := jsonutil.Marshal(ext) + if err != nil { + return nil, fmt.Errorf("Failed to parse Ext information in Adnuntius: %v", err) + } + + return returnExt, nil + } + return nil, nil +} + +func generateAdUnit(imp openrtb2.Imp, adnuntiusExt openrtb_ext.ImpExtAdnunitus, bidType string) adnRequestAdunit { + adUnit := adnRequestAdunit{ + AuId: adnuntiusExt.Auid, + TargetId: fmt.Sprintf("%s-%s:%s", adnuntiusExt.Auid, imp.ID, bidType), + Dimensions: getImpSizes(imp, bidType), + } + + if adnuntiusExt.MaxDeals > 0 { + adUnit.MaxDeals = adnuntiusExt.MaxDeals + } + return adUnit +} + +func convertMarkupTypeToBidType(markupType openrtb2.MarkupType) openrtb_ext.BidType { + switch markupType { + case openrtb2.MarkupBanner: + return openrtb_ext.BidTypeBanner + case openrtb2.MarkupNative: + return openrtb_ext.BidTypeNative + } + return openrtb_ext.BidTypeBanner +} diff --git a/adapters/adnuntius/adnuntiustest/exemplary/simple-banner.json b/adapters/adnuntius/adnuntiustest/exemplary/simple-banner.json index 1358d08a518..ae5389176fc 100644 --- a/adapters/adnuntius/adnuntiustest/exemplary/simple-banner.json +++ b/adapters/adnuntius/adnuntiustest/exemplary/simple-banner.json @@ -36,7 +36,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -51,7 +52,8 @@ "adUnits": [ { "auId": "0000000000000123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -90,6 +92,7 @@ "adomain": ["google.com"], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/exemplary/simple-native-banner.json b/adapters/adnuntius/adnuntiustest/exemplary/simple-native-banner.json new file mode 100644 index 00000000000..fb20797e1ba --- /dev/null +++ b/adapters/adnuntius/adnuntiustest/exemplary/simple-native-banner.json @@ -0,0 +1,139 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "test-native-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "native": { + "request": "{\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]},{\"event\":2,\"methods\":[1]}],\"assets\":[{\"id\":789,\"required\":1,\"title\":{\"len\":140}},{\"id\":1,\"required\":1,\"img\":{\"type\":3,\"w\":250,\"h\":250}},{\"id\":122,\"required\":1,\"img\":{\"type\":1,\"w\":15,\"h\":15}},{\"id\":2,\"required\":1,\"data\":{\"type\":1}},{\"id\":3,\"required\":1,\"data\":{\"type\":2}},{\"id\":4,\"required\":0,\"data\":{\"type\":3}},{\"id\":5,\"required\":0,\"data\":{\"type\":4}},{\"id\":6,\"required\":0,\"data\":{\"type\":5}},{\"id\":7,\"required\":0,\"data\":{\"type\":6}},{\"id\":8,\"required\":0,\"data\":{\"type\":7}},{\"id\":9,\"required\":0,\"data\":{\"type\":8}},{\"id\":10,\"required\":0,\"data\":{\"type\":9}},{\"id\":11,\"required\":0,\"data\":{\"type\":10}},{\"id\":12,\"required\":0,\"data\":{\"type\":11}}]}" + }, + "ext": { + "bidder": { + "auId": "123" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://whatever.url?format=prebidServer&tzo=0", + "body": { + "adUnits": [ + { + "auId": "123", + "targetId": "123-test-native-id:banner", + "nativeRequest": {}, + "dimensions": [[300,250],[300,600]] + }, + { + "auId": "123", + "targetId": "123-test-native-id:native", + "adType": "NATIVE", + "nativeRequest":{"ortb":{"eventtrackers":[{"event":1,"methods":[1,2]},{"event":2,"methods":[1]}],"assets":[{"id":789,"required":1,"title":{"len":140}},{"id":1,"required":1,"img":{"type":3,"w":250,"h":250}},{"id":122,"required":1,"img":{"type":1,"w":15,"h":15}},{"id":2,"required":1,"data":{"type":1}},{"id":3,"required":1,"data":{"type":2}},{"id":4,"required":0,"data":{"type":3}},{"id":5,"required":0,"data":{"type":4}},{"id":6,"required":0,"data":{"type":5}},{"id":7,"required":0,"data":{"type":6}},{"id":8,"required":0,"data":{"type":7}},{"id":9,"required":0,"data":{"type":8}},{"id":10,"required":0,"data":{"type":9}},{"id":11,"required":0,"data":{"type":10}},{"id":12,"required":0,"data":{"type":11}}]}} + } + ], + "context": "prebid.org", + "metaData": {} + }, + "impIDs":["test-native-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "adUnits": [ + { + "auId": "0000000000000123", + "targetId": "123-test-native-id:banner", + "matchedAdCount": 1, + "html": "", + "responseId": "adn-rsp-900646517", + "ads": [ + { + "destinationUrls": { + "url": "http://www.google.com" + }, + "advertiserDomains": ["google.com"], + "bid": { + "amount": 19.0, + "currency": "NOK" + }, + "adId": "adn-id-1559784094", + "creativeWidth": "980", + "creativeHeight": "240", + "creativeId": "jn9hpzvlsf8cpdmm", + "lineItemId": "q7y9qm5b0xt9htrv" + } + ] + }, + { + "auId": "0000000000000123", + "targetId": "123-test-native-id:native", + "matchedAdCount": 1, + "html": "", + "nativeJson": {"ortb":{"ver":"1.2","assets":[{"id":789,"required":true,"title":{"text":"Adnuntius Forever"}},{"id":1,"required":true,"img":{"type":3,"url":"https://assets.adnuntius.com/cfacah/qz2pmlqb8k2y8wqhzvn8zy8v3m2p209ms0pjk1wjy8x037mx0g.jpg?id=4013198","w":250,"h":250}},{"id":122,"required":true,"img":{"type":1,"url":"https://assets.adnuntius.com/cfacah/f9tcm571y850k8bt8mp7fsfyrnj6lhr1sz99fzxyfkwglq2znp.jpg?id=4013199","w":15,"h":15}},{"id":2,"required":true,"data":{"type":1,"value":"CNN"}},{"id":3,"required":true,"data":{"type":2,"value":"Adnuntius is a glorious company"}},{"id":4,"required":false,"data":{"type":3,"value":"5"}},{"id":5,"required":false,"data":{"type":4,"value":"1001"}},{"id":6,"required":false,"data":{"type":5,"value":"8923"}},{"id":9,"required":false,"data":{"type":8,"value":"555-1234"}},{"id":11,"required":false,"data":{"type":10,"value":"Click on the link to learn more"}},{"id":12,"required":false,"data":{"type":11,"value":"Adnuntius"}}],"link":{"url":"https://delivery.adnuntius.com/c/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw?ct=1640189&r=https%3A%2F%2Fadnuntius.com"},"eventtrackers":[{"event":1,"method":1,"url":"https://delivery.adnuntius.com/b/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw.gif"},{"event":2,"method":1,"url":"https://delivery.adnuntius.com/v/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw.gif"}]}}, + "responseId": "adn-rsp-900646517", + "ads": [ + { + "destinationUrls": { + "url": "http://www.google.com" + }, + "advertiserDomains": ["google.com"], + "bid": { + "amount": 20.0, + "currency": "NOK" + }, + "adId": "adn-id-1559784094", + "creativeWidth": "980", + "creativeHeight": "240", + "creativeId": "jn9hpzvlsf8cpdmm", + "lineItemId": "q7y9qm5b0xt9htrv" + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "adn-id-1559784094", + "impid": "test-native-id", + "price": 20000, + "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":789,\"required\":true,\"title\":{\"text\":\"Adnuntius Forever\"}},{\"id\":1,\"required\":true,\"img\":{\"type\":3,\"url\":\"https://assets.adnuntius.com/cfacah/qz2pmlqb8k2y8wqhzvn8zy8v3m2p209ms0pjk1wjy8x037mx0g.jpg?id=4013198\",\"w\":250,\"h\":250}},{\"id\":122,\"required\":true,\"img\":{\"type\":1,\"url\":\"https://assets.adnuntius.com/cfacah/f9tcm571y850k8bt8mp7fsfyrnj6lhr1sz99fzxyfkwglq2znp.jpg?id=4013199\",\"w\":15,\"h\":15}},{\"id\":2,\"required\":true,\"data\":{\"type\":1,\"value\":\"CNN\"}},{\"id\":3,\"required\":true,\"data\":{\"type\":2,\"value\":\"Adnuntius is a glorious company\"}},{\"id\":4,\"required\":false,\"data\":{\"type\":3,\"value\":\"5\"}},{\"id\":5,\"required\":false,\"data\":{\"type\":4,\"value\":\"1001\"}},{\"id\":6,\"required\":false,\"data\":{\"type\":5,\"value\":\"8923\"}},{\"id\":9,\"required\":false,\"data\":{\"type\":8,\"value\":\"555-1234\"}},{\"id\":11,\"required\":false,\"data\":{\"type\":10,\"value\":\"Click on the link to learn more\"}},{\"id\":12,\"required\":false,\"data\":{\"type\":11,\"value\":\"Adnuntius\"}}],\"link\":{\"url\":\"https://delivery.adnuntius.com/c/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw?ct=1640189&r=https%3A%2F%2Fadnuntius.com\"},\"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"https://delivery.adnuntius.com/b/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw.gif\"},{\"event\":2,\"method\":1,\"url\":\"https://delivery.adnuntius.com/v/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw.gif\"}]}", + "adid": "adn-id-1559784094", + "adomain": ["google.com"], + "cid": "q7y9qm5b0xt9htrv", + "crid": "jn9hpzvlsf8cpdmm", + "mtype": 4, + "w": 980, + "h": 240 + }, + "type": "native" + } + ], + "currency": "NOK" + } + ] +} diff --git a/adapters/adnuntius/adnuntiustest/exemplary/simple-native.json b/adapters/adnuntius/adnuntiustest/exemplary/simple-native.json new file mode 100644 index 00000000000..8b435acfe76 --- /dev/null +++ b/adapters/adnuntius/adnuntiustest/exemplary/simple-native.json @@ -0,0 +1,97 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "test-native-id", + "native": { + "request": "{\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]},{\"event\":2,\"methods\":[1]}],\"assets\":[{\"id\":789,\"required\":1,\"title\":{\"len\":140}},{\"id\":1,\"required\":1,\"img\":{\"type\":3,\"w\":250,\"h\":250}},{\"id\":122,\"required\":1,\"img\":{\"type\":1,\"w\":15,\"h\":15}},{\"id\":2,\"required\":1,\"data\":{\"type\":1}},{\"id\":3,\"required\":1,\"data\":{\"type\":2}},{\"id\":4,\"required\":0,\"data\":{\"type\":3}},{\"id\":5,\"required\":0,\"data\":{\"type\":4}},{\"id\":6,\"required\":0,\"data\":{\"type\":5}},{\"id\":7,\"required\":0,\"data\":{\"type\":6}},{\"id\":8,\"required\":0,\"data\":{\"type\":7}},{\"id\":9,\"required\":0,\"data\":{\"type\":8}},{\"id\":10,\"required\":0,\"data\":{\"type\":9}},{\"id\":11,\"required\":0,\"data\":{\"type\":10}},{\"id\":12,\"required\":0,\"data\":{\"type\":11}}]}" + }, + "ext": { + "bidder": { + "auId": "123" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://whatever.url?format=prebidServer&tzo=0", + "body": { + "adUnits": [ + { + "auId": "123", + "targetId": "123-test-native-id:native", + "adType": "NATIVE", + "nativeRequest":{"ortb":{"eventtrackers":[{"event":1,"methods":[1,2]},{"event":2,"methods":[1]}],"assets":[{"id":789,"required":1,"title":{"len":140}},{"id":1,"required":1,"img":{"type":3,"w":250,"h":250}},{"id":122,"required":1,"img":{"type":1,"w":15,"h":15}},{"id":2,"required":1,"data":{"type":1}},{"id":3,"required":1,"data":{"type":2}},{"id":4,"required":0,"data":{"type":3}},{"id":5,"required":0,"data":{"type":4}},{"id":6,"required":0,"data":{"type":5}},{"id":7,"required":0,"data":{"type":6}},{"id":8,"required":0,"data":{"type":7}},{"id":9,"required":0,"data":{"type":8}},{"id":10,"required":0,"data":{"type":9}},{"id":11,"required":0,"data":{"type":10}},{"id":12,"required":0,"data":{"type":11}}]}} + } + ], + "context": "prebid.org", + "metaData": {} + }, + "impIDs":["test-native-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "adUnits": [ + { + "auId": "0000000000000123", + "targetId": "123-test-native-id:native", + "matchedAdCount": 1, + "html": "", + "nativeJson": {"ortb":{"ver":"1.2","assets":[{"id":789,"required":true,"title":{"text":"Adnuntius Forever"}},{"id":1,"required":true,"img":{"type":3,"url":"https://assets.adnuntius.com/cfacah/qz2pmlqb8k2y8wqhzvn8zy8v3m2p209ms0pjk1wjy8x037mx0g.jpg?id=4013198","w":250,"h":250}},{"id":122,"required":true,"img":{"type":1,"url":"https://assets.adnuntius.com/cfacah/f9tcm571y850k8bt8mp7fsfyrnj6lhr1sz99fzxyfkwglq2znp.jpg?id=4013199","w":15,"h":15}},{"id":2,"required":true,"data":{"type":1,"value":"CNN"}},{"id":3,"required":true,"data":{"type":2,"value":"Adnuntius is a glorious company"}},{"id":4,"required":false,"data":{"type":3,"value":"5"}},{"id":5,"required":false,"data":{"type":4,"value":"1001"}},{"id":6,"required":false,"data":{"type":5,"value":"8923"}},{"id":9,"required":false,"data":{"type":8,"value":"555-1234"}},{"id":11,"required":false,"data":{"type":10,"value":"Click on the link to learn more"}},{"id":12,"required":false,"data":{"type":11,"value":"Adnuntius"}}],"link":{"url":"https://delivery.adnuntius.com/c/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw?ct=1640189&r=https%3A%2F%2Fadnuntius.com"},"eventtrackers":[{"event":1,"method":1,"url":"https://delivery.adnuntius.com/b/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw.gif"},{"event":2,"method":1,"url":"https://delivery.adnuntius.com/v/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw.gif"}]}}, + "responseId": "adn-rsp-900646517", + "ads": [ + { + "destinationUrls": { + "url": "http://www.google.com" + }, + "advertiserDomains": ["google.com"], + "bid": { + "amount": 20.0, + "currency": "NOK" + }, + "adId": "adn-id-1559784094", + "creativeWidth": "980", + "creativeHeight": "240", + "creativeId": "jn9hpzvlsf8cpdmm", + "lineItemId": "q7y9qm5b0xt9htrv" + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "adn-id-1559784094", + "impid": "test-native-id", + "price": 20000, + "adm": "{\"ver\":\"1.2\",\"assets\":[{\"id\":789,\"required\":true,\"title\":{\"text\":\"Adnuntius Forever\"}},{\"id\":1,\"required\":true,\"img\":{\"type\":3,\"url\":\"https://assets.adnuntius.com/cfacah/qz2pmlqb8k2y8wqhzvn8zy8v3m2p209ms0pjk1wjy8x037mx0g.jpg?id=4013198\",\"w\":250,\"h\":250}},{\"id\":122,\"required\":true,\"img\":{\"type\":1,\"url\":\"https://assets.adnuntius.com/cfacah/f9tcm571y850k8bt8mp7fsfyrnj6lhr1sz99fzxyfkwglq2znp.jpg?id=4013199\",\"w\":15,\"h\":15}},{\"id\":2,\"required\":true,\"data\":{\"type\":1,\"value\":\"CNN\"}},{\"id\":3,\"required\":true,\"data\":{\"type\":2,\"value\":\"Adnuntius is a glorious company\"}},{\"id\":4,\"required\":false,\"data\":{\"type\":3,\"value\":\"5\"}},{\"id\":5,\"required\":false,\"data\":{\"type\":4,\"value\":\"1001\"}},{\"id\":6,\"required\":false,\"data\":{\"type\":5,\"value\":\"8923\"}},{\"id\":9,\"required\":false,\"data\":{\"type\":8,\"value\":\"555-1234\"}},{\"id\":11,\"required\":false,\"data\":{\"type\":10,\"value\":\"Click on the link to learn more\"}},{\"id\":12,\"required\":false,\"data\":{\"type\":11,\"value\":\"Adnuntius\"}}],\"link\":{\"url\":\"https://delivery.adnuntius.com/c/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw?ct=1640189&r=https%3A%2F%2Fadnuntius.com\"},\"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"https://delivery.adnuntius.com/b/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw.gif\"},{\"event\":2,\"method\":1,\"url\":\"https://delivery.adnuntius.com/v/F1i91dCdKGIaWlotJHElIzQfj0T8qblUtK9cVXT1Qk8AAAAQCtjQz9kbGWD4nuZy3q6HaHGLAo_4rvebVEWFar2PLtv390pVPgSqDpWMkf24FSxJzl2pN3R3uB61gWbrxyxDx47w2QxHYYa9qYwhaJJf7EZU6ko47RlaZS6pMq83EjVwS5YbUYtMoEBgt7zNBL_EvrwPbYt3Tw3fZxXGWB4plvHLpE0DWObeaOFyAfI9fJ7MHSx68m7OTe-h35x60bk8NwpCuNBG7r1iW9gsWWzt4LDOuU3OQl0Jcgskc90wCbVsYIXv5PvSBqu4kSuC644UEpdMz1cbsw.gif\"}]}", + "adid": "adn-id-1559784094", + "adomain": ["google.com"], + "cid": "q7y9qm5b0xt9htrv", + "crid": "jn9hpzvlsf8cpdmm", + "mtype": 4, + "w": 980, + "h": 240 + }, + "type": "native" + } + ], + "currency": "NOK" + } + ] +} diff --git a/adapters/adnuntius/adnuntiustest/supplemental/banner-nil-check.json b/adapters/adnuntius/adnuntiustest/supplemental/banner-nil-check.json deleted file mode 100644 index ae6b7cd823b..00000000000 --- a/adapters/adnuntius/adnuntiustest/supplemental/banner-nil-check.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "mockBidRequest": { - "id": "test-request-id", - "user": { - "id": "1kjh3429kjh295jkl" - }, - "device":{ - "ext":{ - "noCookies" : true - } - }, - "imp": [ - { - "id": "test-imp-id", - "ext": { - "bidder": { - "auId": "123" - } - } - } - ] - }, - "expectedMakeRequestsErrors": [ - { - "value": "ignoring imp id=test-imp-id, Adnuntius supports only Banner", - "comparison": "literal" - } - ] -} diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-dealId.json b/adapters/adnuntius/adnuntiustest/supplemental/check-dealId.json index bf263dad3c6..1bc9ef86047 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-dealId.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-dealId.json @@ -36,8 +36,9 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", - "dimensions": [[300,250],[300,600]] + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, + "dimensions": [[300,250],[300,600]] } ], "context": "prebid.org", @@ -52,6 +53,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -92,6 +94,7 @@ "dealid" : "deal_123", "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-legalName-omitted.json b/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-legalName-omitted.json index 75675ae4b50..7dbc98654fe 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-legalName-omitted.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-legalName-omitted.json @@ -50,7 +50,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -71,6 +72,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -114,6 +116,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240, "ext": { diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-legalName.json b/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-legalName.json index f9eebec3612..7ca8c5cf77e 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-legalName.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-legalName.json @@ -50,7 +50,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -71,6 +72,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -115,6 +117,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240, "ext": { diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-omitted.json b/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-omitted.json index 9456c1fd9f4..42bb1c8abcd 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-omitted.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-dsa-advertiser-omitted.json @@ -50,7 +50,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -71,6 +72,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -111,6 +113,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-gdpr.json b/adapters/adnuntius/adnuntiustest/supplemental/check-gdpr.json index 5b5aaf14bb2..97c08b8e1c6 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-gdpr.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-gdpr.json @@ -43,7 +43,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -61,6 +62,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -101,6 +103,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-gross-bids.json b/adapters/adnuntius/adnuntiustest/supplemental/check-gross-bids.json index d2cdf1515da..72eb3dc58f6 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-gross-bids.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-gross-bids.json @@ -36,7 +36,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -54,6 +55,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -93,6 +95,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-native-error.json b/adapters/adnuntius/adnuntiustest/supplemental/check-native-error.json new file mode 100644 index 00000000000..47021c480c6 --- /dev/null +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-native-error.json @@ -0,0 +1,80 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "test-native-id", + "native": { + "request": "{\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]},{\"event\":2,\"methods\":[1]}],\"assets\":[{\"id\":789,\"required\":1,\"title\":{\"len\":140}},{\"id\":1,\"required\":1,\"img\":{\"type\":3,\"w\":250,\"h\":250}},{\"id\":122,\"required\":1,\"img\":{\"type\":1,\"w\":15,\"h\":15}},{\"id\":2,\"required\":1,\"data\":{\"type\":1}},{\"id\":3,\"required\":1,\"data\":{\"type\":2}},{\"id\":4,\"required\":0,\"data\":{\"type\":3}},{\"id\":5,\"required\":0,\"data\":{\"type\":4}},{\"id\":6,\"required\":0,\"data\":{\"type\":5}},{\"id\":7,\"required\":0,\"data\":{\"type\":6}},{\"id\":8,\"required\":0,\"data\":{\"type\":7}},{\"id\":9,\"required\":0,\"data\":{\"type\":8}},{\"id\":10,\"required\":0,\"data\":{\"type\":9}},{\"id\":11,\"required\":0,\"data\":{\"type\":10}},{\"id\":12,\"required\":0,\"data\":{\"type\":11}}]}" + }, + "ext": { + "bidder": { + "auId": "123" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://whatever.url?format=prebidServer&tzo=0", + "body": { + "adUnits": [ + { + "auId": "123", + "targetId": "123-test-native-id:native", + "adType": "NATIVE", + "nativeRequest":{"ortb":{"eventtrackers":[{"event":1,"methods":[1,2]},{"event":2,"methods":[1]}],"assets":[{"id":789,"required":1,"title":{"len":140}},{"id":1,"required":1,"img":{"type":3,"w":250,"h":250}},{"id":122,"required":1,"img":{"type":1,"w":15,"h":15}},{"id":2,"required":1,"data":{"type":1}},{"id":3,"required":1,"data":{"type":2}},{"id":4,"required":0,"data":{"type":3}},{"id":5,"required":0,"data":{"type":4}},{"id":6,"required":0,"data":{"type":5}},{"id":7,"required":0,"data":{"type":6}},{"id":8,"required":0,"data":{"type":7}},{"id":9,"required":0,"data":{"type":8}},{"id":10,"required":0,"data":{"type":9}},{"id":11,"required":0,"data":{"type":10}},{"id":12,"required":0,"data":{"type":11}}]}} + } + ], + "context": "prebid.org", + "metaData": {} + }, + "impIDs":["test-native-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "adUnits": [ + { + "auId": "0000000000000123", + "targetId": "123-test-native-id:native", + "matchedAdCount": 1, + "html": "", + "nativeJson": {}, + "responseId": "adn-rsp-900646517", + "ads": [ + { + "destinationUrls": { + "url": "http://www.google.com" + }, + "advertiserDomains": ["google.com"], + "bid": { + "amount": 20.0, + "currency": "NOK" + }, + "adId": "adn-id-1559784094", + "creativeWidth": "980", + "creativeHeight": "240", + "creativeId": "jn9hpzvlsf8cpdmm", + "lineItemId": "q7y9qm5b0xt9htrv" + } + ] + } + ] + } + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Failed to parse native json where imp id=test-native-id", + "comparison": "literal" + } + ] +} diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-net-bids.json b/adapters/adnuntius/adnuntiustest/supplemental/check-net-bids.json index 27f08b72294..7ff67451a61 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-net-bids.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-net-bids.json @@ -36,7 +36,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -54,6 +55,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -93,6 +95,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-noCookies-parameter.json b/adapters/adnuntius/adnuntiustest/supplemental/check-noCookies-parameter.json index a4c1637bfe0..c13fd7ae533 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-noCookies-parameter.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-noCookies-parameter.json @@ -36,7 +36,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -54,6 +55,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -94,6 +96,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-noCookies.json b/adapters/adnuntius/adnuntiustest/supplemental/check-noCookies.json index 5e8f2f5f8ec..e5f2469cffb 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-noCookies.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-noCookies.json @@ -40,7 +40,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -57,7 +58,8 @@ "adUnits": [ { "auId": "0000000000000123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -98,6 +100,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-order-multi-imp.json b/adapters/adnuntius/adnuntiustest/supplemental/check-order-multi-imp.json index edf902ea6ad..1035bb35c15 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-order-multi-imp.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-order-multi-imp.json @@ -56,12 +56,14 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] }, { "auId": "456", - "targetId": "456-test-imp-id-2", + "targetId": "456-test-imp-id-2:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -76,7 +78,8 @@ "adUnits": [ { "auId": "0000000000000456", - "targetId": "456-test-imp-id-2", + "targetId": "456-test-imp-id-2:banner", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -99,7 +102,8 @@ }, { "auId": "0000000000000123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -138,6 +142,7 @@ "adomain": ["google.com"], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, @@ -153,6 +158,7 @@ "adomain": ["google.com"], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/check-userId.json b/adapters/adnuntius/adnuntiustest/supplemental/check-userId.json index 15cb06084da..7b1a063f1af 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/check-userId.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/check-userId.json @@ -35,7 +35,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -53,6 +54,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -93,6 +95,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/empty-regs-ext.json b/adapters/adnuntius/adnuntiustest/supplemental/empty-regs-ext.json index b4eb94e2cb3..1c1de916804 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/empty-regs-ext.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/empty-regs-ext.json @@ -38,7 +38,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -56,6 +57,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -96,6 +98,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/empty-regs.json b/adapters/adnuntius/adnuntiustest/supplemental/empty-regs.json index aa871612cdd..50e3230eff2 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/empty-regs.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/empty-regs.json @@ -37,7 +37,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -55,6 +56,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -95,6 +97,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/height-error.json b/adapters/adnuntius/adnuntiustest/supplemental/height-error.json index 75df3107aa3..5dbd360067b 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/height-error.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/height-error.json @@ -35,7 +35,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -53,6 +54,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ diff --git a/adapters/adnuntius/adnuntiustest/supplemental/invalid-regs-ext.json b/adapters/adnuntius/adnuntiustest/supplemental/invalid-regs-ext.json index 27e043de1cb..4cf575d348f 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/invalid-regs-ext.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/invalid-regs-ext.json @@ -39,7 +39,7 @@ }, "expectedMakeRequestsErrors": [ { - "value": "failed to parse URL: [failed to parse Adnuntius endpoint: failed to parse ExtRegs in Adnuntius GDPR check: expect { or n, but found \"]", + "value": "failed to parse URL: [failed to parse GDPR information: failed to parse ExtRegs in Adnuntius GDPR check: expect { or n, but found \"]", "comparison": "literal" } ] diff --git a/adapters/adnuntius/adnuntiustest/supplemental/max-deals-test.json b/adapters/adnuntius/adnuntiustest/supplemental/max-deals-test.json index cca9d50ff7c..cb59ef59dd9 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/max-deals-test.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/max-deals-test.json @@ -37,7 +37,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]], "maxDeals": 2 } @@ -143,6 +144,7 @@ "adomain": ["google.com"], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 300, "h": 250 }, @@ -159,6 +161,7 @@ "cid": "6l5w2d29kz3vkprq", "crid": "dl0knc1lnks9jgvx", "dealid": "deal_123", + "mtype": 1, "w": 300, "h": 250 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/native-error.json b/adapters/adnuntius/adnuntiustest/supplemental/native-error.json deleted file mode 100644 index cf21ba0ef99..00000000000 --- a/adapters/adnuntius/adnuntiustest/supplemental/native-error.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "mockBidRequest": { - "id": "unsupported-native-request", - "imp": [ - { - "id": "unsupported-native-imp", - "native": { - "ver": "1.1" - }, - "ext": { - "bidder": { - "auId": "1" - } - } - } - ] - }, - "expectedMakeRequestsErrors": [ - { - "value": "ignoring imp id=unsupported-native-imp, Adnuntius supports only Banner", - "comparison": "literal" - } - ] -} diff --git a/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json b/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json index 42cd7d6372f..6d464e2cad3 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/send-header-information.json @@ -55,7 +55,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -73,6 +74,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -113,6 +115,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/site-ext.json b/adapters/adnuntius/adnuntiustest/supplemental/site-ext.json index 4cd4077703c..4c059192602 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/site-ext.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/site-ext.json @@ -42,7 +42,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -63,6 +64,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -103,6 +105,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/size-check.json b/adapters/adnuntius/adnuntiustest/supplemental/size-check.json index be44843751d..0a616ca9c60 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/size-check.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/size-check.json @@ -33,7 +33,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,600]] } ], @@ -51,6 +52,7 @@ { "auId": "0000000000000123", "targetId": "123-test-imp-id", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -91,6 +93,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/status-400.json b/adapters/adnuntius/adnuntiustest/supplemental/status-400.json index 5a0b4606735..0e3f1afe938 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/status-400.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/status-400.json @@ -32,7 +32,8 @@ "adUnits": [ { "auId": "", - "targetId": "-test-imp-id", + "targetId": "-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], diff --git a/adapters/adnuntius/adnuntiustest/supplemental/test-networks.json b/adapters/adnuntius/adnuntiustest/supplemental/test-networks.json index a8a60393ffb..5a5724e6633 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/test-networks.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/test-networks.json @@ -37,8 +37,9 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", - "dimensions": [[300,250],[300,600]] + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, + "dimensions": [[300,250],[300,600]] } ], "context": "prebid.org", @@ -52,7 +53,8 @@ "adUnits": [ { "auId": "0000000000000123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -91,6 +93,7 @@ "adomain": ["google.com"], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/user-ext-invalid.json b/adapters/adnuntius/adnuntiustest/supplemental/user-ext-invalid.json new file mode 100644 index 00000000000..3e71a4f1aca --- /dev/null +++ b/adapters/adnuntius/adnuntiustest/supplemental/user-ext-invalid.json @@ -0,0 +1,37 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "user": { + "ext":"" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "auId": "123" + } + } + } + ] + }, + "expectedMakeRequestsErrors": [ + { + "value": "failed to parse URL: [failed to parse GDPR information: failed to parse ExtUser in Adnuntius GDPR check: expect { or n, but found \"]", + "comparison": "literal" + } + ] + +} diff --git a/adapters/adnuntius/adnuntiustest/supplemental/user-ext.json b/adapters/adnuntius/adnuntiustest/supplemental/user-ext.json index 83486dd066e..4d3ccb13738 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/user-ext.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/user-ext.json @@ -44,7 +44,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], @@ -61,7 +62,8 @@ "adUnits": [ { "auId": "0000000000000123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "matchedAdCount": 1, "html": "", "responseId": "adn-rsp-900646517", "ads": [ @@ -102,6 +104,7 @@ ], "cid": "q7y9qm5b0xt9htrv", "crid": "jn9hpzvlsf8cpdmm", + "mtype": 1, "w": 980, "h": 240 }, diff --git a/adapters/adnuntius/adnuntiustest/supplemental/video-error.json b/adapters/adnuntius/adnuntiustest/supplemental/video-error.json index ed22dc540bf..0beac0a29ae 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/video-error.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/video-error.json @@ -1,9 +1,9 @@ { "mockBidRequest": { - "id": "unsupported-native-request", + "id": "unsupported-video-request", "imp": [ { - "id": "unsupported-native-imp", + "id": "unsupported-video-imp", "video": { "w": 728, "h": 90 @@ -18,8 +18,8 @@ }, "expectedMakeRequestsErrors": [ { - "value": "ignoring imp id=unsupported-native-imp, Adnuntius supports only Banner", + "value": "ignoring imp id=unsupported-video-imp, Adnuntius supports only native and banner", "comparison": "literal" } ] -} +} \ No newline at end of file diff --git a/adapters/adnuntius/adnuntiustest/supplemental/width-error.json b/adapters/adnuntius/adnuntiustest/supplemental/width-error.json index dabc6e62a96..3125eb7c10e 100644 --- a/adapters/adnuntius/adnuntiustest/supplemental/width-error.json +++ b/adapters/adnuntius/adnuntiustest/supplemental/width-error.json @@ -35,7 +35,8 @@ "adUnits": [ { "auId": "123", - "targetId": "123-test-imp-id", + "targetId": "123-test-imp-id:banner", + "nativeRequest": {}, "dimensions": [[300,250],[300,600]] } ], diff --git a/adapters/aidem/aidem.go b/adapters/aidem/aidem.go index d644d83cdf2..6e8a7409594 100644 --- a/adapters/aidem/aidem.go +++ b/adapters/aidem/aidem.go @@ -112,10 +112,6 @@ func getMediaTypeForBid(bid openrtb2.Bid) (openrtb_ext.BidType, error) { return openrtb_ext.BidTypeBanner, nil case openrtb2.MarkupVideo: return openrtb_ext.BidTypeVideo, nil - case openrtb2.MarkupAudio: - return openrtb_ext.BidTypeAudio, nil - case openrtb2.MarkupNative: - return openrtb_ext.BidTypeNative, nil default: return "", fmt.Errorf("Unable to fetch mediaType in multi-format: %s", bid.ImpID) } diff --git a/adapters/algorix/algorixtest/exemplary/sample-banner-web.json b/adapters/algorix/algorixtest/exemplary/sample-banner-web.json new file mode 100644 index 00000000000..5e4aef4196d --- /dev/null +++ b/adapters/algorix/algorixtest/exemplary/sample-banner-web.json @@ -0,0 +1,98 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [{"w": 320, "h": 50}] + }, + "ext": { + "bidder": { + "sid": "testSid", + "token": "testToken", + "region": "APAC" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://apac.xyz.test.com?sid=testSid&token=testToken", + "body": { + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "banner": { + "format": [{"w": 320, "h": 50}], + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "sid": "testSid", + "token": "testToken", + "region": "APAC" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "ttx", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-ads", + "crid": "crid_testid" + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 0.5, + "adm": "some-ads", + "crid": "crid_testid" + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/algorix/algorixtest/exemplary/sample-native-web.json b/adapters/algorix/algorixtest/exemplary/sample-native-web.json new file mode 100644 index 00000000000..a6e35ed8660 --- /dev/null +++ b/adapters/algorix/algorixtest/exemplary/sample-native-web.json @@ -0,0 +1,99 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{\"ver\":\"1.2\",\"context\":1,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":2,\"required\":1,\"title\":{\"len\":90}},{\"id\":6,\"required\":1,\"img\":{\"type\":3,\"wmin\":128,\"hmin\":128,\"mimes\":[\"image/jpg\",\"image/jpeg\",\"image/png\"]}},{\"id\":7,\"required\":1,\"data\":{\"type\":2,\"len\":120}}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "sid": "testSid", + "token": "testToken", + "placementId": "testPlacementId", + "appId": "testAppId" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + } + }, + "httpcalls": [ + { + "expectedRequest": { + "uri": "https://xyz.test.com?sid=testSid&token=testToken", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "native": { + "request": "{\"ver\":\"1.2\",\"context\":1,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":2,\"required\":1,\"title\":{\"len\":90}},{\"id\":6,\"required\":1,\"img\":{\"type\":3,\"wmin\":128,\"hmin\":128,\"mimes\":[\"image/jpg\",\"image/jpeg\",\"image/png\"]}},{\"id\":7,\"required\":1,\"data\":{\"type\":2,\"len\":120}}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "sid": "testSid", + "token": "testToken", + "placementId": "testPlacementId", + "appId": "testAppId" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "8400d766-58b3-47d4-80d7-6658b337d403", + "impid": "test-imp-id", + "price": 1.2, + "adm": "some ads", + "crid": "crid_testid" + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8400d766-58b3-47d4-80d7-6658b337d403", + "impid": "test-imp-id", + "price": 1.2, + "adm": "some ads", + "crid": "crid_testid" + + }, + "type": "native" + } + ] + } + ] +} diff --git a/adapters/algorix/algorixtest/exemplary/sample-video-web.json b/adapters/algorix/algorixtest/exemplary/sample-video-web.json new file mode 100644 index 00000000000..c0ab947a5cd --- /dev/null +++ b/adapters/algorix/algorixtest/exemplary/sample-video-web.json @@ -0,0 +1,106 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 320, + "h": 480, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "sid": "testSid", + "token": "testToken", + "placementId": "testPlacementId", + "appId": "testAppId" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + } + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://xyz.test.com?sid=testSid&token=testToken", + "body": { + "id": "test-request-id", + "imp": [ + { + "id":"test-imp-id", + "video": { + "w": 320, + "h": 480, + "mimes": [ + "video/mp4" + ] + }, + "ext": { + "bidder": { + "sid": "testSid", + "token": "testToken", + "placementId": "testPlacementId", + "appId": "testAppId" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "ttx", + "bid": [{ + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 1.2, + "adm": "some-ads", + "crid": "crid_testid" + }] + } + ], + "cur": "USD" + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 1.2, + "adm": "some-ads", + "crid": "crid_testid" + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/alkimi/alkimi.go b/adapters/alkimi/alkimi.go index 4f924bb15e6..c85b7933158 100644 --- a/adapters/alkimi/alkimi.go +++ b/adapters/alkimi/alkimi.go @@ -24,10 +24,6 @@ type adapter struct { endpoint string } -type extObj struct { - AlkimiBidderExt openrtb_ext.ExtImpAlkimi `json:"bidder"` -} - // Builder builds a new instance of the Alkimi adapter for the given bidder with the given config. func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { endpointURL, err := url.Parse(config.Endpoint) @@ -67,7 +63,7 @@ func updateImps(bidRequest openrtb2.BidRequest) ([]openrtb2.Imp, []error) { updatedImps := make([]openrtb2.Imp, 0, len(bidRequest.Imp)) for _, imp := range bidRequest.Imp { - var bidderExt adapters.ExtImpBidder + var bidderExt = make(map[string]json.RawMessage) var extImpAlkimi openrtb_ext.ExtImpAlkimi if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { @@ -75,7 +71,7 @@ func updateImps(bidRequest openrtb2.BidRequest) ([]openrtb2.Imp, []error) { continue } - if err := jsonutil.Unmarshal(bidderExt.Bidder, &extImpAlkimi); err != nil { + if err := jsonutil.Unmarshal(bidderExt["bidder"], &extImpAlkimi); err != nil { errs = append(errs, err) continue } @@ -92,15 +88,24 @@ func updateImps(bidRequest openrtb2.BidRequest) ([]openrtb2.Imp, []error) { imp.Instl = extImpAlkimi.Instl imp.Exp = extImpAlkimi.Exp - temp := extObj{AlkimiBidderExt: extImpAlkimi} - temp.AlkimiBidderExt.AdUnitCode = imp.ID + temp := extImpAlkimi + temp.AdUnitCode = imp.ID + + tempJson, err := jsonutil.Marshal(temp) + if err != nil { + errs = append(errs, err) + continue + } + + newExt := bidderExt + newExt["bidder"] = tempJson - extJson, err := json.Marshal(temp) + newExtJson, err := jsonutil.Marshal(newExt) if err != nil { errs = append(errs, err) continue } - imp.Ext = extJson + imp.Ext = newExtJson updatedImps = append(updatedImps, imp) } diff --git a/adapters/appnexus/appnexus.go b/adapters/appnexus/appnexus.go index eb7b71272cf..a25f3f31640 100644 --- a/adapters/appnexus/appnexus.go +++ b/adapters/appnexus/appnexus.go @@ -90,7 +90,7 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E continue } - memberId := impExtIncoming.Bidder.Member + memberId := string(impExtIncoming.Bidder.Member) if memberId != "" { // The Appnexus API requires a Member ID in the URL. This means the request may fail if // different impressions have different member IDs. @@ -288,7 +288,7 @@ func handleLegacyParams(appnexusExt *openrtb_ext.ExtImpAppnexus) { } func validateAppnexusExt(appnexusExt *openrtb_ext.ExtImpAppnexus) error { - if appnexusExt.PlacementId == 0 && (appnexusExt.InvCode == "" || appnexusExt.Member == "") { + if appnexusExt.PlacementId == 0 && (appnexusExt.InvCode == "" || string(appnexusExt.Member) == "") { return &errortypes.BadInput{ Message: "No placement or member+invcode provided", } diff --git a/adapters/appnexus/appnexustest/supplemental/member-as-int-test.json b/adapters/appnexus/appnexustest/supplemental/member-as-int-test.json new file mode 100644 index 00000000000..69f8469ef9b --- /dev/null +++ b/adapters/appnexus/appnexustest/supplemental/member-as-int-test.json @@ -0,0 +1,151 @@ +{ + "mockBidRequest": { + "id": "some-req-id", + "imp": [ + { + "id": "some-imp-id", + "native": { + "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}", + "ver": "1.1" + }, + "ext": { + "bidder": { + "member": 103, + "inv_code": "abc" + } + } + } + ], + "site": { + "domain": "prebid.org", + "page": "prebid.org" + }, + "device": { + "ip": "152.193.6.74" + }, + "user": { + "id": "db089de9-a62e-4861-a881-0ff15e052516", + "buyeruid": "8299345306627569435" + }, + "tmax": 500 + }, + "httpcalls": [ + { + "expectedRequest": { + "uri": "http://ib.adnxs.com/openrtb2?member_id=103", + "body": { + "id": "some-req-id", + "imp": [ + { + "id": "some-imp-id", + "native": { + "request": "{\"ver\":\"1.1\",\"context\":1,\"contextsubtype\":11,\"plcmttype\":4,\"plcmtcnt\":1,\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":500}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1,\"hmin\":1}},{\"id\":3,\"required\":0,\"data\":{\"type\":1,\"len\":200}},{\"id\":4,\"required\":0,\"data\":{\"type\":2,\"len\":15000}},{\"id\":5,\"required\":0,\"data\":{\"type\":6,\"len\":40}},{\"id\":6,\"required\":0,\"data\":{\"type\":500}}]}", + "ver": "1.1" + }, + "tagid": "abc", + "ext": { + "appnexus": {} + } + } + ], + "ext": { + "appnexus": { + "hb_source": 5 + } + }, + "site": { + "domain": "prebid.org", + "page": "prebid.org" + }, + "device": { + "ip": "152.193.6.74" + }, + "user": { + "id": "db089de9-a62e-4861-a881-0ff15e052516", + "buyeruid": "8299345306627569435" + }, + "tmax": 500 + }, + "impIDs":["some-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "some-req-id", + "seatbid": [ + { + "bid": [ + { + "id": "928185755156387460", + "impid": "some-imp-id", + "price": 1.000000, + "adid": "69595837", + "adm": "{}", + "adomain": [ + "appnexus.com" + ], + "iurl": "http://nym1-ib.adnxs.com/cr?id=69595837", + "cid": "958", + "crid": "69595837", + "cat": [ + "IAB3-1" + ], + "ext": { + "appnexus": { + "brand_id": 350, + "brand_category_id": 350, + "auction_id": 5607483846416358664, + "bidder_id": 2, + "bid_ad_type": 3, + "deal_priority": 5 + } + } + } + ], + "seat": "958" + } + ], + "bidid": "8141327771600527856", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "928185755156387460", + "impid": "some-imp-id", + "price": 1, + "adm": "{}", + "adid": "69595837", + "adomain": [ + "appnexus.com" + ], + "iurl": "http://nym1-ib.adnxs.com/cr?id=69595837", + "cid": "958", + "crid": "69595837", + "cat": [ + "IAB3-1" + ], + "ext": { + "appnexus": { + "brand_id": 350, + "brand_category_id": 350, + "auction_id": 5607483846416358664, + "bidder_id": 2, + "bid_ad_type": 3, + "deal_priority": 5 + } + } + }, + "type": "native" + } + ] + } + ] + } + \ No newline at end of file diff --git a/adapters/appnexus/params_test.go b/adapters/appnexus/params_test.go index e828bf57da7..225b1ac3231 100644 --- a/adapters/appnexus/params_test.go +++ b/adapters/appnexus/params_test.go @@ -47,6 +47,7 @@ var validParams = []string{ `{"placementId":123,"position":"above"}`, `{"placement_id":123,"position":"below"}`, `{"member":"123","inv_code":"456"}`, + `{"member":123,"inv_code":"456"}`, `{"placementId":123, "keywords":[{"key":"foo","value":["bar"]}]}`, `{"placement_id":123, "keywords":[{"key":"foo","value":["bar", "baz"]}]}`, `{"placement_id":123, "keywords":[{"key":"foo"}]}`, @@ -66,9 +67,11 @@ var invalidParams = []string{ `[]`, `{}`, `{"placement_id":123, "placementId":123}`, + `{"member":123}`, `{"member":"123"}`, `{"member":"123","invCode":45}`, `{"placementId":"123","member":"123","invCode":45}`, + `{"placementId":"123","member":"123","invCode":"45"}`, `{"placement_id":123, "position":"left"}`, `{"placement_id":123, "position":"left"}`, `{"placement_id":123, "reserve":"45"}`, diff --git a/adapters/bidder.go b/adapters/bidder.go index 0818120b783..e4862cb2df5 100644 --- a/adapters/bidder.go +++ b/adapters/bidder.go @@ -148,6 +148,7 @@ type ExtraRequestInfo struct { PbsEntryPoint metrics.RequestType GlobalPrivacyControlHeader string CurrencyConversions currency.Conversions + PreferredMediaType openrtb_ext.BidType } func NewExtraRequestInfo(c currency.Conversions) ExtraRequestInfo { diff --git a/adapters/connatix/connatix.go b/adapters/connatix/connatix.go index d2f900d9c22..11cf7a146ab 100644 --- a/adapters/connatix/connatix.go +++ b/adapters/connatix/connatix.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" "strings" "github.com/buger/jsonparser" @@ -155,9 +156,33 @@ func splitRequests(imps []openrtb2.Imp, request *openrtb2.BidRequest, uri string return nil, errs } + endpoint, err := url.Parse(uri) + if err != nil { + errs = append(errs, err) + return nil, errs + } + + if request.User != nil { + userID := strings.TrimSpace(request.User.BuyerUID) + + if len(userID) > 0 { + queryParams := url.Values{} + + if strings.HasPrefix(userID, "1-") { + queryParams.Add("dc", "us-east-2") + } else if strings.HasPrefix(userID, "2-") { + queryParams.Add("dc", "us-west-2") + } else if strings.HasPrefix(userID, "3-") { + queryParams.Add("dc", "eu-west-1") + } + + endpoint.RawQuery = queryParams.Encode() + } + } + resArr = append(resArr, &adapters.RequestData{ Method: "POST", - Uri: uri, + Uri: endpoint.String(), Body: reqJSON, Headers: headers, ImpIDs: openrtb_ext.GetImpIDs(request.Imp), diff --git a/adapters/connatix/connatixtest/supplemental/bid-request-eu-user.json b/adapters/connatix/connatixtest/supplemental/bid-request-eu-user.json new file mode 100644 index 00000000000..a5bb8550aba --- /dev/null +++ b/adapters/connatix/connatixtest/supplemental/bid-request-eu-user.json @@ -0,0 +1,176 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 500, + "user": { + "buyeruid": "3-some-user" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789", + "ext": { + "prebid": { + "source": "test", + "version": "1.0.0" + } + } + }, + "imp": [ + { + "id": "some-imp-id", + "tagid": "some-tag-id", + "banner": { + "format":[ + { + "w": 320, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "placementId": "some-placement-id", + "viewabilityPercentage": 0.6 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com?dc=eu-west-1", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-imp-id", + "tagid": "some-tag-id", + "banner": { + "w": 320, + "h": 50, + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "displaymanagerver": "test-1.0.0", + "ext": { + "connatix": { + "placementId": "some-placement-id", + "viewabilityPercentage": 0.6 + } + } + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + }, + "ext": { + "prebid": { + "source": "test", + "version": "1.0.0" + } + } + }, + "user": { + "buyeruid": "3-some-user" + }, + "tmax": 500 + }, + "impIDs": [ + "some-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "seatbid": [ + { + "bid": [ + { + "id": "some-bid-id", + "impid": "some-imp-id", + "price": 0.52, + "adm": "some-test-ad", + "adomain": [ + "test.com" + ], + "crid": "112233", + "w": 320, + "h": 50, + "ext": { + "connatix": { + "mediaType": "banner" + } + } + } + ], + "seat": "connatix", + "group": 0 + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "some-bid-id", + "impid": "some-imp-id", + "price": 0.52, + "adm": "some-test-ad", + "crid": "112233", + "adomain": [ + "test.com" + ], + "w": 320, + "h": 50, + "ext": { + "connatix": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } \ No newline at end of file diff --git a/adapters/connatix/connatixtest/supplemental/bid-request-no-user.json b/adapters/connatix/connatixtest/supplemental/bid-request-no-user.json new file mode 100644 index 00000000000..75ddabdef7c --- /dev/null +++ b/adapters/connatix/connatixtest/supplemental/bid-request-no-user.json @@ -0,0 +1,170 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 500, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789", + "ext": { + "prebid": { + "source": "test", + "version": "1.0.0" + } + } + }, + "imp": [ + { + "id": "some-imp-id", + "tagid": "some-tag-id", + "banner": { + "format":[ + { + "w": 320, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "placementId": "some-placement-id", + "viewabilityPercentage": 0.6 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-imp-id", + "tagid": "some-tag-id", + "banner": { + "w": 320, + "h": 50, + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "displaymanagerver": "test-1.0.0", + "ext": { + "connatix": { + "placementId": "some-placement-id", + "viewabilityPercentage": 0.6 + } + } + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + }, + "ext": { + "prebid": { + "source": "test", + "version": "1.0.0" + } + } + }, + "tmax": 500 + }, + "impIDs": [ + "some-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "seatbid": [ + { + "bid": [ + { + "id": "some-bid-id", + "impid": "some-imp-id", + "price": 0.52, + "adm": "some-test-ad", + "adomain": [ + "test.com" + ], + "crid": "112233", + "w": 320, + "h": 50, + "ext": { + "connatix": { + "mediaType": "banner" + } + } + } + ], + "seat": "connatix", + "group": 0 + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "some-bid-id", + "impid": "some-imp-id", + "price": 0.52, + "adm": "some-test-ad", + "crid": "112233", + "adomain": [ + "test.com" + ], + "w": 320, + "h": 50, + "ext": { + "connatix": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } \ No newline at end of file diff --git a/adapters/connatix/connatixtest/supplemental/bid-request-us-east-user.json b/adapters/connatix/connatixtest/supplemental/bid-request-us-east-user.json new file mode 100644 index 00000000000..279047b168e --- /dev/null +++ b/adapters/connatix/connatixtest/supplemental/bid-request-us-east-user.json @@ -0,0 +1,176 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 500, + "user": { + "buyeruid": "1-some-user" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789", + "ext": { + "prebid": { + "source": "test", + "version": "1.0.0" + } + } + }, + "imp": [ + { + "id": "some-imp-id", + "tagid": "some-tag-id", + "banner": { + "format":[ + { + "w": 320, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "placementId": "some-placement-id", + "viewabilityPercentage": 0.6 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com?dc=us-east-2", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-imp-id", + "tagid": "some-tag-id", + "banner": { + "w": 320, + "h": 50, + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "displaymanagerver": "test-1.0.0", + "ext": { + "connatix": { + "placementId": "some-placement-id", + "viewabilityPercentage": 0.6 + } + } + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + }, + "ext": { + "prebid": { + "source": "test", + "version": "1.0.0" + } + } + }, + "user": { + "buyeruid": "1-some-user" + }, + "tmax": 500 + }, + "impIDs": [ + "some-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "seatbid": [ + { + "bid": [ + { + "id": "some-bid-id", + "impid": "some-imp-id", + "price": 0.52, + "adm": "some-test-ad", + "adomain": [ + "test.com" + ], + "crid": "112233", + "w": 320, + "h": 50, + "ext": { + "connatix": { + "mediaType": "banner" + } + } + } + ], + "seat": "connatix", + "group": 0 + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "some-bid-id", + "impid": "some-imp-id", + "price": 0.52, + "adm": "some-test-ad", + "crid": "112233", + "adomain": [ + "test.com" + ], + "w": 320, + "h": 50, + "ext": { + "connatix": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } \ No newline at end of file diff --git a/adapters/connatix/connatixtest/supplemental/bid-request-us-west-user.json b/adapters/connatix/connatixtest/supplemental/bid-request-us-west-user.json new file mode 100644 index 00000000000..6b12ebda6cf --- /dev/null +++ b/adapters/connatix/connatixtest/supplemental/bid-request-us-west-user.json @@ -0,0 +1,176 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 500, + "user": { + "buyeruid": "2-some-user" + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": [ + "IAB22-1" + ], + "bundle": "com.app.awesome", + "name": "Awesome App", + "domain": "awesomeapp.com", + "id": "123456789", + "ext": { + "prebid": { + "source": "test", + "version": "1.0.0" + } + } + }, + "imp": [ + { + "id": "some-imp-id", + "tagid": "some-tag-id", + "banner": { + "format":[ + { + "w": 320, + "h": 50 + } + ] + }, + "ext": { + "bidder": { + "placementId": "some-placement-id", + "viewabilityPercentage": 0.6 + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://example.com?dc=us-west-2", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-imp-id", + "tagid": "some-tag-id", + "banner": { + "w": 320, + "h": 50, + "format": [ + { + "w": 320, + "h": 50 + } + ] + }, + "displaymanagerver": "test-1.0.0", + "ext": { + "connatix": { + "placementId": "some-placement-id", + "viewabilityPercentage": 0.6 + } + } + } + ], + "app": { + "id": "123456789", + "name": "Awesome App", + "bundle": "com.app.awesome", + "domain": "awesomeapp.com", + "cat": [ + "IAB22-1" + ], + "publisher": { + "id": "123456789" + }, + "ext": { + "prebid": { + "source": "test", + "version": "1.0.0" + } + } + }, + "user": { + "buyeruid": "2-some-user" + }, + "tmax": 500 + }, + "impIDs": [ + "some-imp-id" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-response-id", + "seatbid": [ + { + "bid": [ + { + "id": "some-bid-id", + "impid": "some-imp-id", + "price": 0.52, + "adm": "some-test-ad", + "adomain": [ + "test.com" + ], + "crid": "112233", + "w": 320, + "h": 50, + "ext": { + "connatix": { + "mediaType": "banner" + } + } + } + ], + "seat": "connatix", + "group": 0 + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "some-bid-id", + "impid": "some-imp-id", + "price": 0.52, + "adm": "some-test-ad", + "crid": "112233", + "adomain": [ + "test.com" + ], + "w": 320, + "h": 50, + "ext": { + "connatix": { + "mediaType": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] + } \ No newline at end of file diff --git a/adapters/eplanning/eplanning.go b/adapters/eplanning/eplanning.go index dc8ab900ea3..e3d3f0c1bbc 100644 --- a/adapters/eplanning/eplanning.go +++ b/adapters/eplanning/eplanning.go @@ -1,12 +1,12 @@ package eplanning import ( + "encoding/json" "math/rand" "net/http" "net/url" - "strings" - "regexp" + "strings" "fmt" @@ -195,6 +195,13 @@ func (adapter *EPlanningAdapter) MakeRequests(request *openrtb2.BidRequest, reqI query.Set("vctx", strconv.Itoa(impType)) query.Set("vv", vastVersionDefault) } + if request.Source != nil && request.Source.Ext != nil { + err := setSchain(request.Source.Ext, &query) + if err != nil { + errors = append(errors, err) + return nil, errors + } + } uriObj.RawQuery = query.Encode() uri := uriObj.String() @@ -212,6 +219,101 @@ func (adapter *EPlanningAdapter) MakeRequests(request *openrtb2.BidRequest, reqI return requests, errors } +func setSchain(ext json.RawMessage, query *url.Values) error { + openRtbSchain, err := unmarshalSupplyChain(ext) + if err != nil { + return err + } + if openRtbSchain == nil || len(openRtbSchain.Nodes) > 2 { + return nil + } + + schainValue, err := makeSupplyChain(*openRtbSchain) + if err != nil { + return err + } + + if schainValue != "" { + query.Set("sch", schainValue) + } + + return nil +} + +func unmarshalSupplyChain(ext json.RawMessage) (*openrtb2.SupplyChain, error) { + var extSChain openrtb_ext.ExtRequestPrebidSChain + err := jsonutil.Unmarshal(ext, &extSChain) + if err != nil { + return nil, err + } + return &extSChain.SChain, nil +} + +func makeSupplyChain(openRtbSchain openrtb2.SupplyChain) (string, error) { + if len(openRtbSchain.Nodes) == 0 { + return "", nil + } + + const schainPrefixFmt = "%s,%d" + const schainNodeFmt = "!%s,%s,%s,%s,%s,%s,%s" + schainPrefix := fmt.Sprintf(schainPrefixFmt, openRtbSchain.Ver, openRtbSchain.Complete) + var sb strings.Builder + sb.WriteString(schainPrefix) + for _, node := range openRtbSchain.Nodes { + nodeValues := []any{ + node.ASI, node.SID, node.HP, node.RID, node.Name, node.Domain, node.Ext, + } + formattedValues, err := formatNodeValues(nodeValues) + if err != nil { + return "", err + } + + schainNode := fmt.Sprintf(schainNodeFmt, formattedValues...) + sb.WriteString(schainNode) + } + + return sb.String(), nil +} + +func formatNodeValues(nodeValues []any) ([]any, error) { + var formattedValues []any + for _, value := range nodeValues { + formattedValue, err := makeNodeValue(value) + if err != nil { + return nil, err + } + formattedValues = append(formattedValues, formattedValue) + } + return formattedValues, nil +} + +func makeNodeValue(nodeParam any) (string, error) { + switch nodeParam := nodeParam.(type) { + case string: + // url.QueryEscape() follows the application/x-www-form-urlencoded convention, which encodes spaces as + and RFC 3986 encodes as %20 + return strings.ReplaceAll(url.QueryEscape(nodeParam), "+", "%20"), nil + case *int8: + pointer := nodeParam + if pointer == nil { + return "", nil + } + return makeNodeValue(int(*pointer)) + case int: + return strconv.Itoa(nodeParam), nil + case json.RawMessage: + if nodeParam != nil { + freeFormJson, err := json.Marshal(nodeParam) + if err != nil { + return "", err + } + return makeNodeValue(string(freeFormJson)) + } + return "", nil + default: + return "", nil + } +} + func isMobileDevice(request *openrtb2.BidRequest) bool { return request.Device != nil && (request.Device.DeviceType == adcom1.DeviceMobile || request.Device.DeviceType == adcom1.DevicePhone || request.Device.DeviceType == adcom1.DeviceTablet) } diff --git a/adapters/eplanning/eplanning_test.go b/adapters/eplanning/eplanning_test.go index 1d220184c6b..08af3b36b1c 100644 --- a/adapters/eplanning/eplanning_test.go +++ b/adapters/eplanning/eplanning_test.go @@ -1,12 +1,11 @@ package eplanning import ( - "testing" - "github.com/prebid/prebid-server/v3/adapters" "github.com/prebid/prebid-server/v3/adapters/adapterstest" "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/openrtb_ext" + "testing" ) func TestJsonSamples(t *testing.T) { diff --git a/adapters/eplanning/eplanningtest/supplemental/bid-with-0-nodes-schain.json b/adapters/eplanning/eplanningtest/supplemental/bid-with-0-nodes-schain.json new file mode 100644 index 00000000000..26d3faa9f0b --- /dev/null +++ b/adapters/eplanning/eplanningtest/supplemental/bid-with-0-nodes-schain.json @@ -0,0 +1,87 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "source": { + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [] + } + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "ci": "12345" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://rtb.e-planning.net/pbs/1/12345/1/FILE/ROS?e=300x250%3A300x250&ncb=1&ur=FILE", + "body": {}, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "sI": { "k": "12345" }, + "sec": "ROS", + "sp": [ + { + "k": "300x250", + "a": [{ + "i": "123456789abcdef", + "pr": "0.5", + "adm": "
test
", + "crid": "abcdef123456789", + "id": "adid12345", + "w": 300, + "h": 250 + }] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "123456789abcdef", + "impid": "test-imp-id", + "price": 0.5, + "adm": "
test
", + "adid": "adid12345", + "crid": "abcdef123456789", + "w": 300, + "h": 250 + }, + "type": "banner" + } + ] + } + ] + } \ No newline at end of file diff --git a/adapters/eplanning/eplanningtest/supplemental/bid-with-2-nodes-schain.json b/adapters/eplanning/eplanningtest/supplemental/bid-with-2-nodes-schain.json new file mode 100644 index 00000000000..0a6276ce1a9 --- /dev/null +++ b/adapters/eplanning/eplanningtest/supplemental/bid-with-2-nodes-schain.json @@ -0,0 +1,101 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "source": { + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "exchange1.com", + "sid": "1234", + "hp": 1, + "ext": "text" + }, + { + "asi":"exchange2.com", + "sid":"abcd", + "hp":3, + "rid":"bid-request-2", + "domain":"intermediary.com" + } + ] + } + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "ci": "12345" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://rtb.e-planning.net/pbs/1/12345/1/FILE/ROS?e=300x250%3A300x250&ncb=1&sch=1.0%2C1%21exchange1.com%2C1234%2C1%2C%2C%2C%2C%2522text%2522%21exchange2.com%2Cabcd%2C3%2Cbid-request-2%2C%2Cintermediary.com%2C&ur=FILE", + "body": {}, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "sI": { "k": "12345" }, + "sec": "ROS", + "sp": [ + { + "k": "300x250", + "a": [{ + "i": "123456789abcdef", + "pr": "0.5", + "adm": "
test
", + "crid": "abcdef123456789", + "id": "adid12345", + "w": 300, + "h": 250 + }] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "123456789abcdef", + "impid": "test-imp-id", + "price": 0.5, + "adm": "
test
", + "adid": "adid12345", + "crid": "abcdef123456789", + "w": 300, + "h": 250 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/eplanning/eplanningtest/supplemental/bid-with-3-nodes-schain.json b/adapters/eplanning/eplanningtest/supplemental/bid-with-3-nodes-schain.json new file mode 100644 index 00000000000..84fef06a92e --- /dev/null +++ b/adapters/eplanning/eplanningtest/supplemental/bid-with-3-nodes-schain.json @@ -0,0 +1,106 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "source": { + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "exchange1.com", + "sid": "1234", + "hp": 1, + "ext": "text" + }, + { + "asi": "exchange2.com", + "sid": "abcd", + "hp": 1, + "ext": 1 + }, + { + "asi": "exchange3.com", + "sid": "abcdf", + "hp": 1, + "ext": 1 + } + ] + } + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "ci": "12345" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://rtb.e-planning.net/pbs/1/12345/1/FILE/ROS?e=300x250%3A300x250&ncb=1&ur=FILE", + "body": {}, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "sI": { "k": "12345" }, + "sec": "ROS", + "sp": [ + { + "k": "300x250", + "a": [{ + "i": "123456789abcdef", + "pr": "0.5", + "adm": "
test
", + "crid": "abcdef123456789", + "id": "adid12345", + "w": 300, + "h": 250 + }] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "123456789abcdef", + "impid": "test-imp-id", + "price": 0.5, + "adm": "
test
", + "adid": "adid12345", + "crid": "abcdef123456789", + "w": 300, + "h": 250 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/eplanning/eplanningtest/supplemental/bid-with-schain-slim.json b/adapters/eplanning/eplanningtest/supplemental/bid-with-schain-slim.json new file mode 100644 index 00000000000..83ad385b3ac --- /dev/null +++ b/adapters/eplanning/eplanningtest/supplemental/bid-with-schain-slim.json @@ -0,0 +1,94 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "source": { + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "exchange1.com", + "sid": "1234", + "rid":"bid-request", + "name":"publisher1, Inc." + } + ] + } + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "ci": "12345" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://rtb.e-planning.net/pbs/1/12345/1/FILE/ROS?e=300x250%3A300x250&ncb=1&sch=1.0%2C1%21exchange1.com%2C1234%2C%2Cbid-request%2Cpublisher1%252C%2520Inc.%2C%2C&ur=FILE", + "body": {}, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "sI": { "k": "12345" }, + "sec": "ROS", + "sp": [ + { + "k": "300x250", + "a": [{ + "i": "123456789abcdef", + "pr": "0.5", + "adm": "
test
", + "crid": "abcdef123456789", + "id": "adid12345", + "w": 300, + "h": 250 + }] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "123456789abcdef", + "impid": "test-imp-id", + "price": 0.5, + "adm": "
test
", + "adid": "adid12345", + "crid": "abcdef123456789", + "w": 300, + "h": 250 + }, + "type": "banner" + } + ] + } + ] + } \ No newline at end of file diff --git a/adapters/eplanning/eplanningtest/supplemental/bid-with-schain-unmarshal-error.json b/adapters/eplanning/eplanningtest/supplemental/bid-with-schain-unmarshal-error.json new file mode 100644 index 00000000000..d371911ff7a --- /dev/null +++ b/adapters/eplanning/eplanningtest/supplemental/bid-with-schain-unmarshal-error.json @@ -0,0 +1,38 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "source": { + "ext": { + "schain": "" + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "ci": "12345" + } + } + } + ] + }, + "expectedMakeRequestsErrors": [ + { + "value": "cannot unmarshal openrtb_ext.ExtRequestPrebidSChain.SChain: expect { or n, but found ", + "comparison": "startswith" + } + ] +} \ No newline at end of file diff --git a/adapters/eplanning/eplanningtest/supplemental/bid-with-schain.json b/adapters/eplanning/eplanningtest/supplemental/bid-with-schain.json new file mode 100644 index 00000000000..02b591625ba --- /dev/null +++ b/adapters/eplanning/eplanningtest/supplemental/bid-with-schain.json @@ -0,0 +1,94 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "source": { + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "exchange1.com", + "sid": "1234", + "hp": 1, + "ext": "text" + } + ] + } + } + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "ci": "12345" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://rtb.e-planning.net/pbs/1/12345/1/FILE/ROS?e=300x250%3A300x250&ncb=1&sch=1.0%2C1%21exchange1.com%2C1234%2C1%2C%2C%2C%2C%2522text%2522&ur=FILE", + "body": {}, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "sI": { "k": "12345" }, + "sec": "ROS", + "sp": [ + { + "k": "300x250", + "a": [{ + "i": "123456789abcdef", + "pr": "0.5", + "adm": "
test
", + "crid": "abcdef123456789", + "id": "adid12345", + "w": 300, + "h": 250 + }] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "123456789abcdef", + "impid": "test-imp-id", + "price": 0.5, + "adm": "
test
", + "adid": "adid12345", + "crid": "abcdef123456789", + "w": 300, + "h": 250 + }, + "type": "banner" + } + ] + } + ] +} \ No newline at end of file diff --git a/adapters/infoawarebidder.go b/adapters/infoawarebidder.go index e7b82c96a31..6ccc039b48f 100644 --- a/adapters/infoawarebidder.go +++ b/adapters/infoawarebidder.go @@ -54,55 +54,84 @@ func (i *InfoAwareBidder) MakeRequests(request *openrtb2.BidRequest, reqInfo *Ex allowedMediaTypes = i.info.dooh } - // Filtering imps is quite expensive (array filter with large, non-pointer elements)... but should be rare, - // because it only happens if the publisher makes a really bad request. - // - // To avoid allocating new arrays and copying in the normal case, we'll make one pass to - // see if any imps need to be removed, and another to do the removing if necessary. - numToFilter, errs := pruneImps(request.Imp, allowedMediaTypes) - - // If all imps in bid request come with unsupported media types, exit - if numToFilter == len(request.Imp) { - return nil, append(errs, &errortypes.Warning{Message: "Bid request didn't contain media types supported by the bidder"}) + updated, updatedImps, errs := pruneImps(request.Imp, allowedMediaTypes, i.info.multiformat, reqInfo.PreferredMediaType) + if updated { + request.Imp = updatedImps } - if numToFilter != 0 { - // Filter out imps with unsupported media types - filteredImps, newErrs := filterImps(request.Imp, numToFilter) - request.Imp = filteredImps - errs = append(errs, newErrs...) + // If all imps in bid request are invalid, exit + if len(request.Imp) == 0 { + return nil, append(errs, &errortypes.Warning{Message: "Bid request didn't contain media types supported by the bidder"}) } + reqs, delegateErrs := i.Bidder.MakeRequests(request, reqInfo) return reqs, append(errs, delegateErrs...) } -// pruneImps trims invalid media types from each imp, and returns true if any of the -// Imps have _no_ valid Media Types left. -func pruneImps(imps []openrtb2.Imp, allowedTypes parsedSupports) (int, []error) { - numToFilter := 0 +// pruneImps trims imps that don't match the allowed types and removes imps that don't have the allowed types. +// It also handles multi-format restrictions if the bidder doesn't support multi-format impressions. +func pruneImps(imps []openrtb2.Imp, allowedTypes parsedSupports, multiformatSupport bool, preferredMediaType openrtb_ext.BidType) (bool, []openrtb2.Imp, []error) { + var updated bool var errs []error + writeIndex := 0 + for i := 0; i < len(imps); i++ { - if !allowedTypes.banner && imps[i].Banner != nil { - imps[i].Banner = nil + imp := &imps[i] // Work with pointer to avoid copying + + // Prune unsupported media types + if !allowedTypes.banner && imp.Banner != nil { + imp.Banner = nil errs = append(errs, &errortypes.Warning{Message: fmt.Sprintf("request.imp[%d] uses banner, but this bidder doesn't support it", i)}) } - if !allowedTypes.video && imps[i].Video != nil { - imps[i].Video = nil + if !allowedTypes.video && imp.Video != nil { + imp.Video = nil errs = append(errs, &errortypes.Warning{Message: fmt.Sprintf("request.imp[%d] uses video, but this bidder doesn't support it", i)}) } - if !allowedTypes.audio && imps[i].Audio != nil { - imps[i].Audio = nil + if !allowedTypes.audio && imp.Audio != nil { + imp.Audio = nil errs = append(errs, &errortypes.Warning{Message: fmt.Sprintf("request.imp[%d] uses audio, but this bidder doesn't support it", i)}) } - if !allowedTypes.native && imps[i].Native != nil { - imps[i].Native = nil + if !allowedTypes.native && imp.Native != nil { + imp.Native = nil errs = append(errs, &errortypes.Warning{Message: fmt.Sprintf("request.imp[%d] uses native, but this bidder doesn't support it", i)}) } - if !hasAnyTypes(&imps[i]) { - numToFilter = numToFilter + 1 + + // Skip if all media types are gone + numOfFormats := countNumberOfFormats(imp) + if numOfFormats == 0 { + errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("request.imp[%d] has no supported MediaTypes. It will be ignored", i)}) + updated = true + continue + } + + // Handle multi-format restrictions for bidders that don't support multi-format impressions + if !multiformatSupport && numOfFormats > 1 { + + removeImp, multiformatErrs := adjustImpForPreferredMediaType(imp, preferredMediaType) + + //remove the Imp if the bidder doesn't support the preferred media type or preferred media type is not defined + if removeImp { + errs = append(errs, multiformatErrs...) + updated = true + continue + } + + if multiformatErrs != nil { + errs = append(errs, multiformatErrs...) + } + } + + // Move valid imp to the correct position + if updated { + imps[writeIndex] = imps[i] } + writeIndex++ } - return numToFilter, errs + // If updated, return the modified slice; otherwise, return the original slice + if updated { + return true, imps[:writeIndex], errs + } + return false, imps, errs } func parseAllowedTypes(allowedTypes []openrtb_ext.BidType) (allowBanner bool, allowVideo bool, allowAudio bool, allowNative bool) { @@ -121,28 +150,29 @@ func parseAllowedTypes(allowedTypes []openrtb_ext.BidType) (allowBanner bool, al return } -func hasAnyTypes(imp *openrtb2.Imp) bool { - return imp.Banner != nil || imp.Video != nil || imp.Audio != nil || imp.Native != nil -} - -func filterImps(imps []openrtb2.Imp, numToFilter int) ([]openrtb2.Imp, []error) { - newImps := make([]openrtb2.Imp, 0, len(imps)-numToFilter) - errs := make([]error, 0, numToFilter) - for i := 0; i < len(imps); i++ { - if hasAnyTypes(&imps[i]) { - newImps = append(newImps, imps[i]) - } else { - errs = append(errs, &errortypes.BadInput{Message: fmt.Sprintf("request.imp[%d] has no supported MediaTypes. It will be ignored", i)}) - } +func countNumberOfFormats(imp *openrtb2.Imp) int { + count := 0 + if imp.Banner != nil { + count++ } - return newImps, errs + if imp.Video != nil { + count++ + } + if imp.Audio != nil { + count++ + } + if imp.Native != nil { + count++ + } + return count } // Structs to handle parsed bidder info, so we aren't reparsing every request type parsedBidderInfo struct { - app parsedSupports - site parsedSupports - dooh parsedSupports + app parsedSupports + site parsedSupports + dooh parsedSupports + multiformat bool } type parsedSupports struct { @@ -172,5 +202,99 @@ func parseBidderInfo(info config.BidderInfo) parsedBidderInfo { parsedInfo.dooh.enabled = true parsedInfo.dooh.banner, parsedInfo.dooh.video, parsedInfo.dooh.audio, parsedInfo.dooh.native = parseAllowedTypes(info.Capabilities.DOOH.MediaTypes) } + parsedInfo.multiformat = IsMultiFormatSupported(info) + return parsedInfo } + +// adjustImpForPreferredMediaType modifies the given impression to retain only the preferred media type. +// It returns the updated impression and any error encountered during the adjustment process. +func adjustImpForPreferredMediaType(imp *openrtb2.Imp, preferredMediaType openrtb_ext.BidType) (bool, []error) { + var errors []error + var removeImp bool + // Clear irrelevant media types based on the preferred media type. + switch preferredMediaType { + case openrtb_ext.BidTypeBanner: + if imp.Banner != nil { + removeVideo(imp, &errors) + removeAudio(imp, &errors) + removeNative(imp, &errors) + } else { + return true, []error{&errortypes.BadInput{Message: fmt.Sprintf("Imp %s does not have a preferred BANNER media type. It will be ignored.", imp.ID)}} + } + case openrtb_ext.BidTypeVideo: + if imp.Video != nil { + removeBanner(imp, &errors) + removeAudio(imp, &errors) + removeNative(imp, &errors) + } else { + return true, []error{&errortypes.BadInput{Message: fmt.Sprintf("Imp %s does not have a preferred VIDEO media type. It will be ignored.", imp.ID)}} + } + case openrtb_ext.BidTypeAudio: + if imp.Audio != nil { + removeBanner(imp, &errors) + removeVideo(imp, &errors) + removeNative(imp, &errors) + } else { + return true, []error{&errortypes.BadInput{Message: fmt.Sprintf("Imp %s does not have a preferred AUDIO media type. It will be ignored.", imp.ID)}} + } + case openrtb_ext.BidTypeNative: + if imp.Native != nil { + removeBanner(imp, &errors) + removeVideo(imp, &errors) + removeAudio(imp, &errors) + } else { + return true, []error{&errortypes.BadInput{Message: fmt.Sprintf("Imp %s does not have a preferred NATIVE media type. It will be ignored.", imp.ID)}} + } + case "": + return true, []error{&errortypes.BadInput{Message: fmt.Sprintf("Removing the imp %s as the bidder does not support multi-format and preferred media type is not defined for the bidder", imp.ID)}} + default: + return true, []error{&errortypes.BadInput{Message: fmt.Sprintf("Imp %s has an invalid preferred media type: %s. It will be ignored.", imp.ID, preferredMediaType)}} + } + + return removeImp, errors +} + +// Function to remove the banner media type from the impression and add a warning. +func removeBanner(imp *openrtb2.Imp, errors *[]error) { + if imp.Banner != nil { + addWarning(errors, imp.ID, openrtb_ext.BidTypeBanner) + imp.Banner = nil + } +} + +// Function to remove the video media type from the impression and add a warning. +func removeVideo(imp *openrtb2.Imp, errors *[]error) { + if imp.Video != nil { + addWarning(errors, imp.ID, openrtb_ext.BidTypeVideo) + imp.Video = nil + } +} + +// Function to remove the Native media type from the impression and add a warning. +func removeNative(imp *openrtb2.Imp, errors *[]error) { + if imp.Native != nil { + addWarning(errors, imp.ID, openrtb_ext.BidTypeNative) + imp.Native = nil + } +} + +// Function to remove the Audio media type from the impression and add a warning. +func removeAudio(imp *openrtb2.Imp, errors *[]error) { + if imp.Audio != nil { + addWarning(errors, imp.ID, openrtb_ext.BidTypeAudio) + imp.Audio = nil + } +} + +// Function to add a warning message to the list. +func addWarning(errors *[]error, impID string, mediaTypeName openrtb_ext.BidType) { + *errors = append(*errors, &errortypes.Warning{Message: fmt.Sprintf("Imp %s uses %s, removing %s as the bidder doesn't support multi-format", impID, mediaTypeName, mediaTypeName)}) +} + +func IsMultiFormatSupported(bidderInfo config.BidderInfo) bool { + if bidderInfo.OpenRTB != nil && bidderInfo.OpenRTB.MultiformatSupported != nil { + return *bidderInfo.OpenRTB.MultiformatSupported + } + return true +} diff --git a/adapters/infoawarebidder_test.go b/adapters/infoawarebidder_test.go index 4eb2dbffe30..5a28e506cc5 100644 --- a/adapters/infoawarebidder_test.go +++ b/adapters/infoawarebidder_test.go @@ -1,11 +1,10 @@ -package adapters_test +package adapters import ( "errors" "testing" "github.com/prebid/openrtb/v20/openrtb2" - "github.com/prebid/prebid-server/v3/adapters" "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/errortypes" "github.com/prebid/prebid-server/v3/openrtb_ext" @@ -22,11 +21,11 @@ func TestAppNotSupported(t *testing.T) { }, }, } - constrained := adapters.BuildInfoAwareBidder(bidder, info) + constrained := BuildInfoAwareBidder(bidder, info) bids, errs := constrained.MakeRequests(&openrtb2.BidRequest{ Imp: []openrtb2.Imp{{ID: "imp-1", Banner: &openrtb2.Banner{}}}, App: &openrtb2.App{}, - }, &adapters.ExtraRequestInfo{}) + }, &ExtraRequestInfo{}) if !assert.Len(t, errs, 1) { return } @@ -44,11 +43,11 @@ func TestSiteNotSupported(t *testing.T) { }, }, } - constrained := adapters.BuildInfoAwareBidder(bidder, info) + constrained := BuildInfoAwareBidder(bidder, info) bids, errs := constrained.MakeRequests(&openrtb2.BidRequest{ Imp: []openrtb2.Imp{{ID: "imp-1", Banner: &openrtb2.Banner{}}}, Site: &openrtb2.Site{}, - }, &adapters.ExtraRequestInfo{}) + }, &ExtraRequestInfo{}) if !assert.Len(t, errs, 1) { return } @@ -66,11 +65,11 @@ func TestDOOHNotSupported(t *testing.T) { }, }, } - constrained := adapters.BuildInfoAwareBidder(bidder, info) + constrained := BuildInfoAwareBidder(bidder, info) bids, errs := constrained.MakeRequests(&openrtb2.BidRequest{ Imp: []openrtb2.Imp{{ID: "imp-1", Banner: &openrtb2.Banner{}}}, DOOH: &openrtb2.DOOH{}, - }, &adapters.ExtraRequestInfo{}) + }, &ExtraRequestInfo{}) require.Len(t, errs, 1) assert.EqualError(t, errs[0], "this bidder does not support dooh requests") assert.IsType(t, &errortypes.Warning{}, errs[0]) @@ -93,7 +92,7 @@ func TestImpFiltering(t *testing.T) { }, } - constrained := adapters.BuildInfoAwareBidder(bidder, info) + constrained := BuildInfoAwareBidder(bidder, info) testCases := []struct { description string @@ -120,6 +119,7 @@ func TestImpFiltering(t *testing.T) { }, expectedErrors: []error{ &errortypes.BadInput{Message: "request.imp[0] uses video, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[0] has no supported MediaTypes. It will be ignored"}, &errortypes.BadInput{Message: "Bid request didn't contain media types supported by the bidder"}, }, expectedImpLen: 0, @@ -136,8 +136,11 @@ func TestImpFiltering(t *testing.T) { }, expectedErrors: []error{ &errortypes.BadInput{Message: "request.imp[0] uses video, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[0] has no supported MediaTypes. It will be ignored"}, &errortypes.BadInput{Message: "request.imp[1] uses native, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[1] has no supported MediaTypes. It will be ignored"}, &errortypes.BadInput{Message: "request.imp[2] uses audio, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[2] has no supported MediaTypes. It will be ignored"}, &errortypes.BadInput{Message: "Bid request didn't contain media types supported by the bidder"}, }, expectedImpLen: 0, @@ -166,9 +169,9 @@ func TestImpFiltering(t *testing.T) { }, expectedErrors: []error{ &errortypes.BadInput{Message: "request.imp[1] uses native, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[1] has no supported MediaTypes. It will be ignored"}, &errortypes.BadInput{Message: "request.imp[2] uses native, but this bidder doesn't support it"}, &errortypes.BadInput{Message: "request.imp[3] uses banner, but this bidder doesn't support it"}, - &errortypes.BadInput{Message: "request.imp[1] has no supported MediaTypes. It will be ignored"}, &errortypes.BadInput{Message: "request.imp[3] has no supported MediaTypes. It will be ignored"}, }, expectedImpLen: 2, @@ -188,7 +191,7 @@ func TestImpFiltering(t *testing.T) { } for _, test := range testCases { - actualAdapterRequests, actualErrs := constrained.MakeRequests(test.inBidRequest, &adapters.ExtraRequestInfo{}) + actualAdapterRequests, actualErrs := constrained.MakeRequests(test.inBidRequest, &ExtraRequestInfo{}) // Assert the request.Imp slice was correctly filtered and if MakeRequest() was called by asserting // the corresponding error messages were returned @@ -201,19 +204,602 @@ func TestImpFiltering(t *testing.T) { } } +func TestImpFilteringForMultiFormatRequests(t *testing.T) { + bidder := &mockBidder{} + var falseValue bool + info := config.BidderInfo{ + Capabilities: &config.CapabilitiesInfo{ + Site: &config.PlatformInfo{ + MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner, openrtb_ext.BidTypeVideo, openrtb_ext.BidTypeNative, openrtb_ext.BidTypeAudio}, + }, + App: &config.PlatformInfo{ + MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeBanner}, + }, + DOOH: &config.PlatformInfo{ + MediaTypes: []openrtb_ext.BidType{openrtb_ext.BidTypeNative}, + }, + }, + OpenRTB: &config.OpenRTBInfo{ + MultiformatSupported: &falseValue, + }, + } + + constrained := BuildInfoAwareBidder(bidder, info) + + testCases := []struct { + description string + inBidRequest *openrtb2.BidRequest + inExtraRequestInfo *ExtraRequestInfo + expectedErrors []error + expectedImpLen int + }{ + { + description: "All imps with preferred media type, MakeRequest() call expected", + inBidRequest: &openrtb2.BidRequest{ + Imp: []openrtb2.Imp{ + { + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + }, + { + ID: "imp-2", + Banner: &openrtb2.Banner{}, + Native: &openrtb2.Native{}, + }, + }, + Site: &openrtb2.Site{}, + }, + inExtraRequestInfo: &ExtraRequestInfo{ + PreferredMediaType: openrtb_ext.BidTypeBanner, + }, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses video, removing video as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-2 uses native, removing native as the bidder doesn't support multi-format"}, + }, + expectedImpLen: 2, + }, + { + description: "Some imps with preferred media type, MakeRequest() call expected", + inBidRequest: &openrtb2.BidRequest{ + Imp: []openrtb2.Imp{ + { + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + }, + { + ID: "imp-2", + Video: &openrtb2.Video{}, + Native: &openrtb2.Native{}, + }, + { + ID: "imp-3", + Video: &openrtb2.Video{}, + Audio: &openrtb2.Audio{}, + }, + }, + Site: &openrtb2.Site{}, + }, + inExtraRequestInfo: &ExtraRequestInfo{ + PreferredMediaType: openrtb_ext.BidTypeBanner, + }, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses video, removing video as the bidder doesn't support multi-format"}, + &errortypes.BadInput{Message: "Imp imp-2 does not have a preferred BANNER media type. It will be ignored."}, + &errortypes.BadInput{Message: "Imp imp-3 does not have a preferred BANNER media type. It will be ignored."}, + }, + expectedImpLen: 1, + }, + { + description: "No imps with preferred media type, MakeRequest() call not expected", + inBidRequest: &openrtb2.BidRequest{ + Imp: []openrtb2.Imp{ + { + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + }, + { + ID: "imp-2", + Video: &openrtb2.Video{}, + Native: &openrtb2.Native{}, + }, + }, + Site: &openrtb2.Site{}, + }, + inExtraRequestInfo: &ExtraRequestInfo{ + PreferredMediaType: openrtb_ext.BidTypeAudio, + }, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Imp imp-1 does not have a preferred AUDIO media type. It will be ignored."}, + &errortypes.BadInput{Message: "Imp imp-2 does not have a preferred AUDIO media type. It will be ignored."}, + &errortypes.BadInput{Message: "Bid request didn't contain media types supported by the bidder"}, + }, + expectedImpLen: 0, + }, + { + description: "preferred media type not defined, MakeRequest() call not expected", + inBidRequest: &openrtb2.BidRequest{ + Imp: []openrtb2.Imp{ + { + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + }, + }, + Site: &openrtb2.Site{}, + }, + inExtraRequestInfo: &ExtraRequestInfo{ + PreferredMediaType: "", + }, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Removing the imp imp-1 as the bidder does not support multi-format and preferred media type is not defined for the bidder"}, + }, + expectedImpLen: 0, + }, + } + + for _, test := range testCases { + actualAdapterRequests, actualErrs := constrained.MakeRequests(test.inBidRequest, test.inExtraRequestInfo) + + for i, expectedErr := range test.expectedErrors { + assert.EqualError(t, expectedErr, actualErrs[i].Error(), "Test failed. Error[%d] in error list mismatch: %s", i, test.description) + } + assert.Len(t, actualAdapterRequests, test.expectedImpLen, "Test failed. Incorrect length of filtered imps: %s", test.description) + } +} + +func TestAdjustImpForPreferredMediaType(t *testing.T) { + testCases := []struct { + description string + inImp openrtb2.Imp + preferredMediaType openrtb_ext.BidType + expectedImp openrtb2.Imp + expectedErrors []error + }{ + { + description: "Multiformat impression with all media types and preferred media type Banner", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + Audio: &openrtb2.Audio{}, + Native: &openrtb2.Native{}, + }, + preferredMediaType: openrtb_ext.BidTypeBanner, + expectedImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + }, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses video, removing video as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-1 uses audio, removing audio as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-1 uses native, removing native as the bidder doesn't support multi-format"}, + }, + }, + { + description: "Multiformat impression with all media types and preferred media type Video", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + Audio: &openrtb2.Audio{}, + Native: &openrtb2.Native{}, + }, + preferredMediaType: openrtb_ext.BidTypeVideo, + expectedImp: openrtb2.Imp{ + ID: "imp-1", + Video: &openrtb2.Video{}, + }, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses banner, removing banner as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-1 uses audio, removing audio as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-1 uses native, removing native as the bidder doesn't support multi-format"}, + }, + }, + { + description: "Multiformat impression with all media types and preferred media type Audio", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + Audio: &openrtb2.Audio{}, + Native: &openrtb2.Native{}, + }, + preferredMediaType: openrtb_ext.BidTypeAudio, + expectedImp: openrtb2.Imp{ + ID: "imp-1", + Audio: &openrtb2.Audio{}, + }, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses banner, removing banner as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-1 uses video, removing video as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-1 uses native, removing native as the bidder doesn't support multi-format"}, + }, + }, + { + description: "Multiformat impression with all media types and preferred media type Native", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + Audio: &openrtb2.Audio{}, + Native: &openrtb2.Native{}, + }, + preferredMediaType: openrtb_ext.BidTypeNative, + expectedImp: openrtb2.Imp{ + ID: "imp-1", + Native: &openrtb2.Native{}, + }, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses banner, removing banner as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-1 uses video, removing video as the bidder doesn't support multi-format"}, + &errortypes.Warning{Message: "Imp imp-1 uses audio, removing audio as the bidder doesn't support multi-format"}, + }, + }, + { + description: "Invalid Banner media type", + inImp: openrtb2.Imp{ + ID: "imp-1", + Video: &openrtb2.Video{}, + }, + preferredMediaType: openrtb_ext.BidTypeBanner, + expectedImp: openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Imp imp-1 does not have a preferred BANNER media type. It will be ignored."}, + }, + }, + { + description: "Invalid Video media type", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + }, + preferredMediaType: openrtb_ext.BidTypeVideo, + expectedImp: openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Imp imp-1 does not have a preferred VIDEO media type. It will be ignored."}, + }, + }, + { + description: "Invalid Audio media type", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + }, + preferredMediaType: openrtb_ext.BidTypeAudio, + expectedImp: openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Imp imp-1 does not have a preferred AUDIO media type. It will be ignored."}, + }, + }, + { + description: "Invalid Native media type", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + }, + preferredMediaType: openrtb_ext.BidTypeNative, + expectedImp: openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Imp imp-1 does not have a preferred NATIVE media type. It will be ignored."}, + }, + }, + { + description: "Invalid preferred media type", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + }, + preferredMediaType: "invalid", + expectedImp: openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Imp imp-1 has an invalid preferred media type: invalid. It will be ignored."}, + }, + }, + { + description: "Multiformat impression with preferred media type not defined", + inImp: openrtb2.Imp{ + ID: "imp-1", + Banner: &openrtb2.Banner{}, + Video: &openrtb2.Video{}, + Audio: &openrtb2.Audio{}, + Native: &openrtb2.Native{}, + }, + preferredMediaType: "", + expectedImp: openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Removing the imp imp-1 as the bidder does not support multi-format and preferred media type is not defined for the bidder"}, + }, + }, + } + + for _, test := range testCases { + _, actualErrs := adjustImpForPreferredMediaType(&test.inImp, test.preferredMediaType) + if test.expectedErrors != nil { + for i, expectedErr := range test.expectedErrors { + assert.EqualError(t, expectedErr, actualErrs[i].Error(), "Test failed. Error[%d] in error list mismatch: %s", i, test.description) + } + } else { + assert.Equal(t, test.expectedImp, test.inImp, test.description) + } + } +} + +func TestIsMultiFormatSupported(t *testing.T) { + trueValue, falseValue := true, false + testCases := []struct { + description string + bidderInfo config.BidderInfo + expected bool + }{ + { + description: "MultiformatSupported is true", + bidderInfo: config.BidderInfo{ + OpenRTB: &config.OpenRTBInfo{ + MultiformatSupported: &trueValue, + }, + }, + expected: true, + }, + { + description: "MultiformatSupported is false", + bidderInfo: config.BidderInfo{ + OpenRTB: &config.OpenRTBInfo{ + MultiformatSupported: &falseValue, + }, + }, + expected: false, + }, + { + description: "MultiformatSupported is nil", + bidderInfo: config.BidderInfo{ + OpenRTB: &config.OpenRTBInfo{ + MultiformatSupported: nil, + }, + }, + expected: true, + }, + { + description: "OpenRTB is nil", + bidderInfo: config.BidderInfo{}, + expected: true, + }, + } + + for _, test := range testCases { + result := IsMultiFormatSupported(test.bidderInfo) + assert.Equal(t, test.expected, result, test.description) + } +} + +func TestPruneImps(t *testing.T) { + testCases := []struct { + description string + imps []openrtb2.Imp + allowedTypes parsedSupports + multiformatSupport bool + preferredMediaType openrtb_ext.BidType + expectedUpdated bool + expectedImps []openrtb2.Imp + expectedErrors []error + }{ + { + description: "No imps to filter", + imps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}}, + }, + allowedTypes: parsedSupports{ + banner: true, + }, + multiformatSupport: true, + expectedUpdated: false, + expectedImps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}}, + }, + expectedErrors: nil, + }, + { + description: "Filter out unsupported banner", + imps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}}, + }, + allowedTypes: parsedSupports{ + banner: false, + }, + multiformatSupport: true, + expectedUpdated: true, + expectedImps: []openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.Warning{Message: "request.imp[0] uses banner, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[0] has no supported MediaTypes. It will be ignored"}, + }, + }, + { + description: "Filter out unsupported video", + imps: []openrtb2.Imp{ + {ID: "imp-1", Video: &openrtb2.Video{}}, + }, + allowedTypes: parsedSupports{ + video: false, + }, + multiformatSupport: true, + expectedUpdated: true, + expectedImps: []openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.Warning{Message: "request.imp[0] uses video, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[0] has no supported MediaTypes. It will be ignored"}, + }, + }, + { + description: "Filter out unsupported audio", + imps: []openrtb2.Imp{ + {ID: "imp-1", Audio: &openrtb2.Audio{}}, + }, + allowedTypes: parsedSupports{ + audio: false, + }, + multiformatSupport: true, + expectedUpdated: true, + expectedImps: []openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.Warning{Message: "request.imp[0] uses audio, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[0] has no supported MediaTypes. It will be ignored"}, + }, + }, + { + description: "Filter out unsupported native", + imps: []openrtb2.Imp{ + {ID: "imp-1", Native: &openrtb2.Native{}}, + }, + allowedTypes: parsedSupports{ + native: false, + }, + multiformatSupport: true, + expectedUpdated: true, + expectedImps: []openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.Warning{Message: "request.imp[0] uses native, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[0] has no supported MediaTypes. It will be ignored"}, + }, + }, + { + description: "Filter out all unsupported types", + imps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}, Video: &openrtb2.Video{}, Audio: &openrtb2.Audio{}, Native: &openrtb2.Native{}}, + }, + allowedTypes: parsedSupports{ + banner: false, + video: false, + audio: false, + native: false, + }, + multiformatSupport: true, + expectedUpdated: true, + expectedImps: []openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.Warning{Message: "request.imp[0] uses banner, but this bidder doesn't support it"}, + &errortypes.Warning{Message: "request.imp[0] uses video, but this bidder doesn't support it"}, + &errortypes.Warning{Message: "request.imp[0] uses audio, but this bidder doesn't support it"}, + &errortypes.Warning{Message: "request.imp[0] uses native, but this bidder doesn't support it"}, + &errortypes.BadInput{Message: "request.imp[0] has no supported MediaTypes. It will be ignored"}, + }, + }, + { + description: "Filter out unsupported multiformat, preferred media type is banner", + imps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}, Video: &openrtb2.Video{}}, + }, + allowedTypes: parsedSupports{ + banner: true, + video: true, + }, + multiformatSupport: false, + preferredMediaType: openrtb_ext.BidTypeBanner, + expectedUpdated: false, + expectedImps: []openrtb2.Imp{{ID: "imp-1", Banner: &openrtb2.Banner{}}}, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses video, removing video as the bidder doesn't support multi-format"}, + }, + }, + { + description: "Filter out unsupported multiformat, preferred media type is video", + imps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}, Video: &openrtb2.Video{}}, + }, + allowedTypes: parsedSupports{ + banner: true, + video: true, + }, + multiformatSupport: false, + preferredMediaType: openrtb_ext.BidTypeVideo, + expectedUpdated: false, + expectedImps: []openrtb2.Imp{{ID: "imp-1", Video: &openrtb2.Video{}}}, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses banner, removing banner as the bidder doesn't support multi-format"}, + }, + }, + { + description: "Filter out unsupported multiformat, preferred media type is video and not present in any imp", + imps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}, Native: &openrtb2.Native{}}, + }, + allowedTypes: parsedSupports{ + banner: true, + video: true, + native: true, + }, + multiformatSupport: false, + preferredMediaType: openrtb_ext.BidTypeVideo, + expectedUpdated: true, + expectedImps: []openrtb2.Imp{}, + expectedErrors: []error{ + &errortypes.BadInput{Message: "Imp imp-1 does not have a preferred VIDEO media type. It will be ignored."}, + }, + }, + { + description: "Multi-imp, Filter out unsupported multiformat, preferred media type is video and present in one imp", + imps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}, Video: &openrtb2.Video{}}, + {ID: "imp-2", Banner: &openrtb2.Banner{}, Native: &openrtb2.Native{}}, + }, + allowedTypes: parsedSupports{ + banner: true, + video: true, + native: true, + }, + multiformatSupport: false, + preferredMediaType: openrtb_ext.BidTypeVideo, + expectedUpdated: true, + expectedImps: []openrtb2.Imp{{ID: "imp-1", Video: &openrtb2.Video{}}}, + expectedErrors: []error{ + &errortypes.Warning{Message: "Imp imp-1 uses banner, removing banner as the bidder doesn't support multi-format"}, + &errortypes.BadInput{Message: "Imp imp-2 does not have a preferred VIDEO media type. It will be ignored."}, + }, + }, + { + description: "Filter out unsupported type and unsupported multiformat, preferred media type is video", + imps: []openrtb2.Imp{ + {ID: "imp-1", Banner: &openrtb2.Banner{}, Video: &openrtb2.Video{}, Native: &openrtb2.Native{}}, + }, + allowedTypes: parsedSupports{ + banner: true, + video: true, + native: false, + }, + multiformatSupport: false, + preferredMediaType: openrtb_ext.BidTypeVideo, + expectedUpdated: false, + expectedImps: []openrtb2.Imp{{ID: "imp-1", Video: &openrtb2.Video{}}}, + expectedErrors: []error{ + &errortypes.Warning{Message: "request.imp[0] uses native, but this bidder doesn't support it"}, + &errortypes.Warning{Message: "Imp imp-1 uses banner, removing banner as the bidder doesn't support multi-format"}, + }, + }, + } + + for _, test := range testCases { + updated, imps, errs := pruneImps(test.imps, test.allowedTypes, test.multiformatSupport, test.preferredMediaType) + assert.Equal(t, test.expectedUpdated, updated, test.description+":Updated") + assert.Equal(t, test.expectedImps, imps, test.description+":Imps") + assert.Equal(t, test.expectedErrors, errs, test.description+":Errors") + } +} + type mockBidder struct { } -func (m *mockBidder) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { - var adapterRequests []*adapters.RequestData +func (m *mockBidder) MakeRequests(request *openrtb2.BidRequest, reqInfo *ExtraRequestInfo) ([]*RequestData, []error) { + var adapterRequests []*RequestData for i := 0; i < len(request.Imp); i++ { - adapterRequests = append(adapterRequests, &adapters.RequestData{}) + adapterRequests = append(adapterRequests, &RequestData{}) } return adapterRequests, nil } -func (m *mockBidder) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { +func (m *mockBidder) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *RequestData, response *ResponseData) (*BidderResponse, []error) { return nil, []error{errors.New("mock MakeBids error")} } diff --git a/adapters/ix/ix.go b/adapters/ix/ix.go index 48becbdcf4c..b24d99eff3b 100644 --- a/adapters/ix/ix.go +++ b/adapters/ix/ix.go @@ -25,15 +25,9 @@ type IxAdapter struct { } type ExtRequest struct { - Prebid *openrtb_ext.ExtRequestPrebid `json:"prebid"` + Prebid *openrtb_ext.ExtRequestPrebid `json:"prebid,omitempty"` SChain *openrtb2.SupplyChain `json:"schain,omitempty"` - IxDiag *IxDiag `json:"ixdiag,omitempty"` -} - -type IxDiag struct { - PbsV string `json:"pbsv,omitempty"` - PbjsV string `json:"pbjsv,omitempty"` - MultipleSiteIds string `json:"multipleSiteIds,omitempty"` + IxDiag json.RawMessage `json:"ixdiag,omitempty"` } type auctionConfig struct { @@ -57,7 +51,7 @@ func (a *IxAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters filteredImps := make([]openrtb2.Imp, 0, len(request.Imp)) requestCopy := *request - ixDiag := &IxDiag{} + ixDiagFields := make(map[string]interface{}) for _, imp := range requestCopy.Imp { var err error @@ -94,9 +88,9 @@ func (a *IxAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters } requestCopy.Imp = filteredImps - setPublisherId(&requestCopy, uniqueSiteIDs, ixDiag) + setPublisherId(&requestCopy, uniqueSiteIDs, ixDiagFields) - err := setIxDiagIntoExtRequest(&requestCopy, ixDiag, version.Ver) + err := setIxDiagIntoExtRequest(&requestCopy, ixDiagFields, version.Ver) if err != nil { errs = append(errs, err) } @@ -112,7 +106,7 @@ func (a *IxAdapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters return requests, errs } -func setPublisherId(requestCopy *openrtb2.BidRequest, uniqueSiteIDs map[string]struct{}, ixDiag *IxDiag) { +func setPublisherId(requestCopy *openrtb2.BidRequest, uniqueSiteIDs map[string]struct{}, ixDiagFields map[string]interface{}) { siteIDs := make([]string, 0, len(uniqueSiteIDs)) for key := range uniqueSiteIDs { siteIDs = append(siteIDs, key) @@ -150,7 +144,7 @@ func setPublisherId(requestCopy *openrtb2.BidRequest, uniqueSiteIDs map[string]s // Sorting siteIDs for predictable output as Go maps don't guarantee order sort.Strings(siteIDs) multipleSiteIDs := strings.Join(siteIDs, ", ") - ixDiag.MultipleSiteIds = multipleSiteIDs + ixDiagFields["multipleSiteIds"] = multipleSiteIDs } } @@ -403,8 +397,8 @@ func extractVersionWithoutCommitHash(ver string) string { return ver // if no hyphen, return the original string } -func setIxDiagIntoExtRequest(request *openrtb2.BidRequest, ixDiag *IxDiag, ver string) error { - extRequest := &ExtRequest{} +func setIxDiagIntoExtRequest(request *openrtb2.BidRequest, ixDiagAdditionalFields map[string]interface{}, ver string) error { + var extRequest ExtRequest if request.Ext != nil { if err := jsonutil.Unmarshal(request.Ext, &extRequest); err != nil { return err @@ -412,28 +406,42 @@ func setIxDiagIntoExtRequest(request *openrtb2.BidRequest, ixDiag *IxDiag, ver s } if extRequest.Prebid != nil && extRequest.Prebid.Channel != nil { - ixDiag.PbjsV = extRequest.Prebid.Channel.Version + ixDiagAdditionalFields["pbjsv"] = extRequest.Prebid.Channel.Version } // Slice commit hash out of version + prebidServerVersion := "unknown" // Default value when the version cannot be determined if ver != "" { - ixDiag.PbsV = extractVersionWithoutCommitHash(ver) + prebidServerVersion = extractVersionWithoutCommitHash(ver) } + ixDiagAdditionalFields["pbsv"] = prebidServerVersion + ixDiagAdditionalFields["pbsp"] = "go" // indicate prebid server implementation use Go version - // Only set request.ext if ixDiag is not empty - if *ixDiag != (IxDiag{}) { - extRequest := &ExtRequest{} - if request.Ext != nil { - if err := jsonutil.Unmarshal(request.Ext, &extRequest); err != nil { - return err - } - } - extRequest.IxDiag = ixDiag - extRequestJson, err := json.Marshal(extRequest) - if err != nil { + var ixDiagMap map[string]interface{} + if extRequest.IxDiag != nil && len(extRequest.IxDiag) > 0 { + if err := jsonutil.Unmarshal(extRequest.IxDiag, &ixDiagMap); err != nil { return err } - request.Ext = extRequestJson + } else { + ixDiagMap = make(map[string]interface{}) + } + + for k, v := range ixDiagAdditionalFields { + ixDiagMap[k] = v } + + ixDiagJSON, err := json.Marshal(ixDiagMap) + if err != nil { + return err + } + + extRequest.IxDiag = ixDiagJSON + + extRequestJSON, err := json.Marshal(extRequest) + if err != nil { + return err + } + + request.Ext = extRequestJSON return nil } diff --git a/adapters/ix/ix_test.go b/adapters/ix/ix_test.go index 48b9796bbb5..d46b69adffc 100644 --- a/adapters/ix/ix_test.go +++ b/adapters/ix/ix_test.go @@ -195,7 +195,7 @@ func TestBuildIxDiag(t *testing.T) { }, expectedRequest: &openrtb2.BidRequest{ ID: "1", - Ext: json.RawMessage(`{"prebid":{"channel":{"name":"web","version":"7.20"}},"ixdiag":{"pbsv":"1.880","pbjsv":"7.20"}}`), + Ext: json.RawMessage(`{"prebid":{"channel":{"name":"web","version":"7.20"}},"ixdiag":{"pbjsv":"7.20","pbsp":"go","pbsv":"1.880"}}`), }, expectError: false, pbsVersion: "1.880-abcdef", @@ -208,7 +208,7 @@ func TestBuildIxDiag(t *testing.T) { }, expectedRequest: &openrtb2.BidRequest{ ID: "1", - Ext: json.RawMessage(`{"prebid":{"server":{"externalurl":"http://localhost:8000","gvlid":0,"datacenter":""}},"ixdiag":{"pbsv":"1.880"}}`), + Ext: json.RawMessage(`{"prebid":{"server":{"externalurl":"http://localhost:8000","gvlid":0,"datacenter":""}},"ixdiag":{"pbsp":"go","pbsv":"1.880"}}`), }, expectError: false, pbsVersion: "1.880-abcdef", @@ -220,7 +220,7 @@ func TestBuildIxDiag(t *testing.T) { }, expectedRequest: &openrtb2.BidRequest{ ID: "1", - Ext: json.RawMessage(`{"prebid":null,"ixdiag":{"pbsv":"1.880"}}`), + Ext: json.RawMessage(`{"ixdiag":{"pbsp":"go","pbsv":"1.880"}}`), }, expectError: false, pbsVersion: "1.880-abcdef", @@ -232,7 +232,7 @@ func TestBuildIxDiag(t *testing.T) { }, expectedRequest: &openrtb2.BidRequest{ ID: "1", - Ext: json.RawMessage(`{"prebid":null,"ixdiag":{"pbsv":"0.23.1"}}`), + Ext: json.RawMessage(`{"ixdiag":{"pbsp":"go","pbsv":"0.23.1"}}`), }, expectError: false, pbsVersion: "0.23.1-3-g4ee257d8", @@ -245,7 +245,7 @@ func TestBuildIxDiag(t *testing.T) { }, expectedRequest: &openrtb2.BidRequest{ ID: "1", - Ext: json.RawMessage(`{"prebid":{"channel":{"name":"web","version":"7.20"}},"ixdiag":{"pbsv":"1.880","pbjsv":"7.20"}}`), + Ext: json.RawMessage(`{"prebid":{"channel":{"name":"web","version":"7.20"}},"ixdiag":{"pbjsv":"7.20","pbsp":"go","pbsv":"1.880"}}`), }, expectError: false, pbsVersion: "1.880", @@ -258,7 +258,20 @@ func TestBuildIxDiag(t *testing.T) { }, expectedRequest: &openrtb2.BidRequest{ ID: "1", - Ext: json.RawMessage(`{"prebid":{"channel":{"name":"web","version":"7.20"}},"ixdiag":{"pbjsv":"7.20"}}`), + Ext: json.RawMessage(`{"prebid":{"channel":{"name":"web","version":"7.20"}},"ixdiag":{"pbjsv":"7.20","pbsp":"go","pbsv":"unknown"}}`), + }, + expectError: false, + pbsVersion: "", + }, + { + description: "request ixdiag contain other fields that should pass-through along with additional version fields", + request: &openrtb2.BidRequest{ + ID: "1", + Ext: json.RawMessage(`{"prebid":{"channel":{"name":"web","version":"7.20"}},"ixdiag":{"msd":2,"msi":1,"nvin":"123"}}`), + }, + expectedRequest: &openrtb2.BidRequest{ + ID: "1", + Ext: json.RawMessage(`{"prebid":{"channel":{"name":"web","version":"7.20"}},"ixdiag":{"msd":2,"msi":1,"nvin":"123","pbjsv":"7.20","pbsp":"go","pbsv":"unknown"}}`), }, expectError: false, pbsVersion: "", @@ -280,8 +293,8 @@ func TestBuildIxDiag(t *testing.T) { for _, test := range testCases { t.Run(test.description, func(t *testing.T) { - ixDiag := &IxDiag{} - err := setIxDiagIntoExtRequest(test.request, ixDiag, test.pbsVersion) + ixDiagFields := make(map[string]interface{}) + err := setIxDiagIntoExtRequest(test.request, ixDiagFields, test.pbsVersion) if test.expectError { assert.NotNil(t, err) } else { diff --git a/adapters/ix/ixtest/exemplary/additional-consent.json b/adapters/ix/ixtest/exemplary/additional-consent.json index dcd388dd505..b3fb8f4e842 100644 --- a/adapters/ix/ixtest/exemplary/additional-consent.json +++ b/adapters/ix/ixtest/exemplary/additional-consent.json @@ -57,6 +57,12 @@ "consented_providers": [1] } } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id"] diff --git a/adapters/ix/ixtest/exemplary/app-site-id.json b/adapters/ix/ixtest/exemplary/app-site-id.json index 4ba3ed52da9..c4ecc31d075 100644 --- a/adapters/ix/ixtest/exemplary/app-site-id.json +++ b/adapters/ix/ixtest/exemplary/app-site-id.json @@ -65,7 +65,9 @@ }, "ext": { "ixdiag": { - "pbjsv": "7.0.0" + "pbjsv": "7.0.0", + "pbsp": "go", + "pbsv": "unknown" }, "prebid": { "channel": { diff --git a/adapters/ix/ixtest/exemplary/banner-no-format.json b/adapters/ix/ixtest/exemplary/banner-no-format.json index 8024a98eb58..cd7db2b6007 100644 --- a/adapters/ix/ixtest/exemplary/banner-no-format.json +++ b/adapters/ix/ixtest/exemplary/banner-no-format.json @@ -41,7 +41,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/exemplary/fledge.json b/adapters/ix/ixtest/exemplary/fledge.json index 876b9785684..34bdf8c5f0b 100644 --- a/adapters/ix/ixtest/exemplary/fledge.json +++ b/adapters/ix/ixtest/exemplary/fledge.json @@ -70,6 +70,12 @@ "publisher": { "id": "569749" } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id"] diff --git a/adapters/ix/ixtest/exemplary/ixdiag.json b/adapters/ix/ixtest/exemplary/ixdiag.json new file mode 100644 index 00000000000..482a7666624 --- /dev/null +++ b/adapters/ix/ixtest/exemplary/ixdiag.json @@ -0,0 +1,239 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id-1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ] + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + }, + { + "id": "test-imp-id-2", + "video": { + "mimes": [ + "video/mp4" + ], + "minduration": 15, + "maxduration": 30, + "protocols": [ + 2, + 3, + 5, + 6, + 7, + 8 + ], + "w": 940, + "h": 560 + }, + "ext": { + "bidder": { + "siteId": "569750" + } + } + }, + { + "id": "test-imp-id-3", + "banner": { + "format": [ + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "siteId": "569751" + } + } + } + ], + "site": { + "page": "https://www.example.com/" + }, + "ext": { + "prebid": { + "channel": { + "name": "web", + "version": "7.0.0" + } + }, + "ixdiag": { + "msd": 2, + "msi": 2, + "mfu": 0, + "ren": false, + "version": "6.29.1" + } + } + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://host/endpoint", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id-1", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "siteId": "569749" + } + } + }, + { + "id": "test-imp-id-2", + "video": { + "mimes": [ + "video/mp4" + ], + "minduration": 15, + "maxduration": 30, + "protocols": [ + 2, + 3, + 5, + 6, + 7, + 8 + ], + "w": 940, + "h": 560 + }, + "ext": { + "bidder": { + "siteId": "569750" + } + } + }, + { + "banner": { + "format": [ + { + "h": 600, + "w": 300 + } + ], + "h": 600, + "w": 300 + }, + "ext": { + "bidder": { + "siteId": "569751" + } + }, + "id": "test-imp-id-3" + } + ], + "site": { + "page": "https://www.example.com/", + "publisher": { + } + }, + "ext": { + "ixdiag": { + "mfu": 0, + "msd": 2, + "msi": 2, + "multipleSiteIds": "569749, 569750, 569751", + "pbjsv": "7.0.0", + "pbsp": "go", + "pbsv": "unknown", + "ren": false, + "version": "6.29.1" + }, + "prebid": { + "channel": { + "name": "web", + "version": "7.0.0" + } + } + } + }, + "impIDs":["test-imp-id-1","test-imp-id-2","test-imp-id-3"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "958", + "bid": [ + { + "id": "7706636740145184841", + "impid": "test-imp-id-1", + "price": 0.5, + "adid": "29681110", + "adm": "some-test-ad", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "h": 250, + "w": 300, + "ext": { + "ix": {} + } + } + ] + } + ], + "bidid": "5778926625248726496", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "7706636740145184841", + "impid": "test-imp-id-1", + "price": 0.5, + "adm": "some-test-ad", + "adid": "29681110", + "adomain": [ + "https://advertiser.example.com" + ], + "cid": "958", + "crid": "29681110", + "w": 300, + "h": 250, + "ext": { + "ix": {} + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/ix/ixtest/exemplary/multi-format-with-ext-prebid-type.json b/adapters/ix/ixtest/exemplary/multi-format-with-ext-prebid-type.json index 25986a1b864..5f624ac735b 100644 --- a/adapters/ix/ixtest/exemplary/multi-format-with-ext-prebid-type.json +++ b/adapters/ix/ixtest/exemplary/multi-format-with-ext-prebid-type.json @@ -75,7 +75,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["multi-format-test-imp-id"] }, diff --git a/adapters/ix/ixtest/exemplary/multi-format-with-mtype.json b/adapters/ix/ixtest/exemplary/multi-format-with-mtype.json index ee571c96af0..9cd869261ef 100644 --- a/adapters/ix/ixtest/exemplary/multi-format-with-mtype.json +++ b/adapters/ix/ixtest/exemplary/multi-format-with-mtype.json @@ -75,7 +75,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["multi-format-test-imp-id"] }, diff --git a/adapters/ix/ixtest/exemplary/multi-imp-multi-size-requests.json b/adapters/ix/ixtest/exemplary/multi-imp-multi-size-requests.json index ca122dee6bd..adbdfee8fb6 100644 --- a/adapters/ix/ixtest/exemplary/multi-imp-multi-size-requests.json +++ b/adapters/ix/ixtest/exemplary/multi-imp-multi-size-requests.json @@ -144,6 +144,12 @@ "publisher": { "id": "569749" } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id-1","test-imp-id-2","test-imp-id-3"] diff --git a/adapters/ix/ixtest/exemplary/multi-imp-requests.json b/adapters/ix/ixtest/exemplary/multi-imp-requests.json index 1ab57a89c3f..44629a3c03b 100644 --- a/adapters/ix/ixtest/exemplary/multi-imp-requests.json +++ b/adapters/ix/ixtest/exemplary/multi-imp-requests.json @@ -197,7 +197,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id-1","test-imp-id-2","test-imp-id-3","test-imp-id-4","test-imp-id-5"] }, diff --git a/adapters/ix/ixtest/exemplary/multibid.json b/adapters/ix/ixtest/exemplary/multibid.json index 5ac68675d28..0232c69a7d5 100644 --- a/adapters/ix/ixtest/exemplary/multibid.json +++ b/adapters/ix/ixtest/exemplary/multibid.json @@ -41,7 +41,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/exemplary/multiple-siteIds.json b/adapters/ix/ixtest/exemplary/multiple-siteIds.json index 93778438945..92b593dd6a3 100644 --- a/adapters/ix/ixtest/exemplary/multiple-siteIds.json +++ b/adapters/ix/ixtest/exemplary/multiple-siteIds.json @@ -148,8 +148,10 @@ }, "ext": { "ixdiag": { - "multipleSiteIds": "569749, 569750, 569751", - "pbjsv": "7.0.0" + "multipleSiteIds": "569749, 569750, 569751", + "pbjsv": "7.0.0", + "pbsp": "go", + "pbsv": "unknown" }, "prebid": { "channel": { diff --git a/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json b/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json index 8d7dcc4c55a..bf8e2809d1a 100644 --- a/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json +++ b/adapters/ix/ixtest/exemplary/native-eventtrackers-compat-12.json @@ -35,7 +35,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/exemplary/no-pub-id.json b/adapters/ix/ixtest/exemplary/no-pub-id.json index 0f280633ad6..579eb20046e 100644 --- a/adapters/ix/ixtest/exemplary/no-pub-id.json +++ b/adapters/ix/ixtest/exemplary/no-pub-id.json @@ -54,6 +54,12 @@ "id": "569749", "name": "publisher-name" } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id"] diff --git a/adapters/ix/ixtest/exemplary/no-pub.json b/adapters/ix/ixtest/exemplary/no-pub.json index 60db036bc8b..30330264497 100644 --- a/adapters/ix/ixtest/exemplary/no-pub.json +++ b/adapters/ix/ixtest/exemplary/no-pub.json @@ -50,6 +50,12 @@ "publisher": { "id": "569749" } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id"] diff --git a/adapters/ix/ixtest/exemplary/simple-audio.json b/adapters/ix/ixtest/exemplary/simple-audio.json index 38131a2bb0e..7920474f7f4 100644 --- a/adapters/ix/ixtest/exemplary/simple-audio.json +++ b/adapters/ix/ixtest/exemplary/simple-audio.json @@ -45,7 +45,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/exemplary/simple-banner-multi-size.json b/adapters/ix/ixtest/exemplary/simple-banner-multi-size.json index 3fef8bf4dad..9544e56ca57 100644 --- a/adapters/ix/ixtest/exemplary/simple-banner-multi-size.json +++ b/adapters/ix/ixtest/exemplary/simple-banner-multi-size.json @@ -68,6 +68,12 @@ "publisher": { "id": "569749" } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id"] diff --git a/adapters/ix/ixtest/exemplary/simple-native.json b/adapters/ix/ixtest/exemplary/simple-native.json index 7d6e378a01d..e3ceb2c55e9 100644 --- a/adapters/ix/ixtest/exemplary/simple-native.json +++ b/adapters/ix/ixtest/exemplary/simple-native.json @@ -35,7 +35,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/exemplary/simple-video.json b/adapters/ix/ixtest/exemplary/simple-video.json index 5a0a3de5950..214e89e7b92 100644 --- a/adapters/ix/ixtest/exemplary/simple-video.json +++ b/adapters/ix/ixtest/exemplary/simple-video.json @@ -61,7 +61,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/exemplary/structured-pod.json b/adapters/ix/ixtest/exemplary/structured-pod.json index 0cc9eafc6f0..1f18efa2dc0 100644 --- a/adapters/ix/ixtest/exemplary/structured-pod.json +++ b/adapters/ix/ixtest/exemplary/structured-pod.json @@ -123,7 +123,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id-1","test-imp-id-2"] }, diff --git a/adapters/ix/ixtest/supplemental/app-site-id-publisher.json b/adapters/ix/ixtest/supplemental/app-site-id-publisher.json index a5837396f54..935813ab44a 100644 --- a/adapters/ix/ixtest/supplemental/app-site-id-publisher.json +++ b/adapters/ix/ixtest/supplemental/app-site-id-publisher.json @@ -69,7 +69,9 @@ }, "ext": { "ixdiag": { - "pbjsv": "7.0.0" + "pbjsv": "7.0.0", + "pbsp": "go", + "pbsv": "unknown" }, "prebid": { "channel": { diff --git a/adapters/ix/ixtest/supplemental/bad-fledge.json b/adapters/ix/ixtest/supplemental/bad-fledge.json index d835d40a33f..a2b52a49625 100644 --- a/adapters/ix/ixtest/supplemental/bad-fledge.json +++ b/adapters/ix/ixtest/supplemental/bad-fledge.json @@ -70,6 +70,12 @@ "publisher": { "id": "569749" } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id"] diff --git a/adapters/ix/ixtest/supplemental/bad-imp-id.json b/adapters/ix/ixtest/supplemental/bad-imp-id.json index 8812625a98b..f110f9d0ab9 100644 --- a/adapters/ix/ixtest/supplemental/bad-imp-id.json +++ b/adapters/ix/ixtest/supplemental/bad-imp-id.json @@ -45,7 +45,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/supplemental/bad-request.json b/adapters/ix/ixtest/supplemental/bad-request.json index 83df3285e74..452e9a4ae3d 100644 --- a/adapters/ix/ixtest/supplemental/bad-request.json +++ b/adapters/ix/ixtest/supplemental/bad-request.json @@ -45,7 +45,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/supplemental/bad-response-body.json b/adapters/ix/ixtest/supplemental/bad-response-body.json index e416123023f..9de15b39175 100644 --- a/adapters/ix/ixtest/supplemental/bad-response-body.json +++ b/adapters/ix/ixtest/supplemental/bad-response-body.json @@ -45,7 +45,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/supplemental/dsa-request.json b/adapters/ix/ixtest/supplemental/dsa-request.json index 969cbbe46d3..755e618ed9d 100644 --- a/adapters/ix/ixtest/supplemental/dsa-request.json +++ b/adapters/ix/ixtest/supplemental/dsa-request.json @@ -102,6 +102,12 @@ ] } } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id"] @@ -191,4 +197,4 @@ ] } ] - } \ No newline at end of file + } diff --git a/adapters/ix/ixtest/supplemental/fledge-no-bid.json b/adapters/ix/ixtest/supplemental/fledge-no-bid.json index d28b7ee0537..46eaea7d6c5 100644 --- a/adapters/ix/ixtest/supplemental/fledge-no-bid.json +++ b/adapters/ix/ixtest/supplemental/fledge-no-bid.json @@ -70,6 +70,12 @@ "publisher": { "id": "569749" } + }, + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } } }, "impIDs":["test-imp-id"] diff --git a/adapters/ix/ixtest/supplemental/multi-imp-requests-error.json b/adapters/ix/ixtest/supplemental/multi-imp-requests-error.json index 6613dce7169..d5b0824b253 100644 --- a/adapters/ix/ixtest/supplemental/multi-imp-requests-error.json +++ b/adapters/ix/ixtest/supplemental/multi-imp-requests-error.json @@ -116,7 +116,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id-2","test-imp-id-3"] }, diff --git a/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json b/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json index 780184f475f..f0d5c09ec77 100644 --- a/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json +++ b/adapters/ix/ixtest/supplemental/native-eventtrackers-empty.json @@ -35,7 +35,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json b/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json index 7b43bcc2caa..b26c02350dd 100644 --- a/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json +++ b/adapters/ix/ixtest/supplemental/native-eventtrackers-missing.json @@ -35,7 +35,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/supplemental/native-missing.json b/adapters/ix/ixtest/supplemental/native-missing.json index cf4305602b9..ba6032c0635 100644 --- a/adapters/ix/ixtest/supplemental/native-missing.json +++ b/adapters/ix/ixtest/supplemental/native-missing.json @@ -35,7 +35,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/supplemental/no-content.json b/adapters/ix/ixtest/supplemental/no-content.json index 76b4dc3545d..ed10286d7e1 100644 --- a/adapters/ix/ixtest/supplemental/no-content.json +++ b/adapters/ix/ixtest/supplemental/no-content.json @@ -45,7 +45,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/supplemental/not-found.json b/adapters/ix/ixtest/supplemental/not-found.json index a3773dc6883..703b252b1cb 100644 --- a/adapters/ix/ixtest/supplemental/not-found.json +++ b/adapters/ix/ixtest/supplemental/not-found.json @@ -45,7 +45,13 @@ } } } - ] + ], + "ext": { + "ixdiag": { + "pbsp": "go", + "pbsv": "unknown" + } + } }, "impIDs":["test-imp-id"] }, diff --git a/adapters/ix/ixtest/supplemental/sid.json b/adapters/ix/ixtest/supplemental/sid.json index 9b5aaf605ba..f3f4e176d31 100644 --- a/adapters/ix/ixtest/supplemental/sid.json +++ b/adapters/ix/ixtest/supplemental/sid.json @@ -63,9 +63,10 @@ "body": { "ext": { "ixdiag": { - "multipleSiteIds": "569749, 569750" - }, - "prebid": null + "multipleSiteIds": "569749, 569750", + "pbsp": "go", + "pbsv": "unknown" + } }, "id": "test-request-id", "imp": [ diff --git a/adapters/kobler/koblertest/exemplary/app-simple_banner.json b/adapters/kobler/koblertest/exemplary/app-simple_banner.json new file mode 100644 index 00000000000..c81f33373e9 --- /dev/null +++ b/adapters/kobler/koblertest/exemplary/app-simple_banner.json @@ -0,0 +1,134 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "device": { + "devicetype": 2 + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": ["IAB22-1"], + "bundle": "com.app.some", + "name": "Some App", + "domain": "some-app.com", + "id": "123456789" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 320, + "h": 100 + } + ] + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://fake.endpoint", + "body": { + "id": "test-request-id", + "device": { + "devicetype": 2 + }, + "app": { + "publisher": { + "id": "123456789" + }, + "cat": ["IAB22-1"], + "bundle": "com.app.some", + "name": "Some App", + "domain": "some-app.com", + "id": "123456789" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "test", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 320, + "h": 100 + } + ] + } + } + ], + "cur": ["USD"] + }, + "impIDs": ["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "kobler" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "test_bid_id", + "impid": "test-imp-id", + "price": 0.27543, + "adm": "", + "cid": "test_cid", + "crid": "test_crid", + "dealid": "test_dealid", + "w": 300, + "h": 250, + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/kobler/koblertest/exemplary/simple_banner.json b/adapters/kobler/koblertest/exemplary/site-simple_banner.json similarity index 100% rename from adapters/kobler/koblertest/exemplary/simple_banner.json rename to adapters/kobler/koblertest/exemplary/site-simple_banner.json diff --git a/adapters/madsense/madsense.go b/adapters/madsense/madsense.go new file mode 100644 index 00000000000..5cf32d64d5a --- /dev/null +++ b/adapters/madsense/madsense.go @@ -0,0 +1,125 @@ +package madsense + +import ( + "net/http" + "net/url" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/errortypes" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" +) + +type adapter struct { + endpoint string +} + +// Builder builds a new instance of the MadSense adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + bidder := &adapter{ + endpoint: config.Endpoint, + } + return bidder, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + reqs := make([]*adapters.RequestData, 0, len(request.Imp)) + var errs []error + + appendReq := func(imps []openrtb2.Imp) { + req, err := a.makeRequest(request, imps) + if err != nil { + errs = append(errs, err) + return + } + if req != nil { + reqs = append(reqs, req) + } + } + + var videoImps []openrtb2.Imp + for i := range request.Imp { + imp := &request.Imp[i] + if imp.Banner != nil { + appendReq(request.Imp[i : i+1]) + } else if imp.Video != nil { + videoImps = append(videoImps, request.Imp[i]) + } + } + + // we support video podding, so we want to send all video impressions in a single request + appendReq(videoImps) + + return reqs, errs +} + +func (a *adapter) makeRequest(request *openrtb2.BidRequest, imps []openrtb2.Imp) (*adapters.RequestData, error) { + if len(imps) == 0 { + return nil, nil + } + ext, err := parseImpExt(&imps[0]) + if err != nil { + return nil, err + } + + request.Imp = imps + body, err := jsonutil.Marshal(request) + if err != nil { + return nil, err + } + + companyId := ext.CompanyId + if request.Test == 1 { + companyId = "test" + } + + return &adapters.RequestData{ + Method: http.MethodPost, + Uri: a.getEndpointURL(companyId), + Body: body, + Headers: getHeaders(request), + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + }, nil +} + +func (a *adapter) getEndpointURL(companyId string) string { + params := url.Values{} + params.Add("company_id", companyId) + return a.endpoint + "?" + params.Encode() +} + +func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if adapters.IsResponseStatusCodeNoContent(response) { + return nil, nil + } + + if err := adapters.CheckResponseStatusCodeForErrors(response); err != nil { + return nil, []error{err} + } + + var resp openrtb2.BidResponse + if err := jsonutil.Unmarshal(response.Body, &resp); err != nil { + return nil, []error{&errortypes.BadServerResponse{ + Message: "Bad Server Response", + }} + } + + var bidErrors []error + bidderResponse := adapters.NewBidderResponseWithBidsCapacity(1) + for i := range resp.SeatBid { + seatBid := &resp.SeatBid[i] + for j := range seatBid.Bid { + bid := &seatBid.Bid[j] + typedBid, err := getTypedBidFromBid(bid) + if err != nil { + bidErrors = append(bidErrors, err) + continue + } + bidderResponse.Bids = append(bidderResponse.Bids, typedBid) + } + } + + return bidderResponse, bidErrors +} diff --git a/adapters/madsense/madsense_test.go b/adapters/madsense/madsense_test.go new file mode 100644 index 00000000000..8093066ac5f --- /dev/null +++ b/adapters/madsense/madsense_test.go @@ -0,0 +1,17 @@ +package madsense + +import ( + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/stretchr/testify/require" + "testing" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderMadSense, config.Adapter{ + Endpoint: "https://test.localhost.com"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + require.NoError(t, buildErr, "Builder returned unexpected error") + adapterstest.RunJSONBidderTest(t, "madsensetest", bidder) +} diff --git a/adapters/madsense/madsensetest/exemplary/banner-app.json b/adapters/madsense/madsensetest/exemplary/banner-app.json new file mode 100644 index 00000000000..bc1b2668fce --- /dev/null +++ b/adapters/madsense/madsensetest/exemplary/banner-app.json @@ -0,0 +1,116 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ua": "user-agent", + "ip": "1.2.3.4" + }, + "app": { + "bundle": "54321" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "uri": "https://test.localhost.com?company_id=9876543", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ua": "user-agent", + "ip": "1.2.3.4" + }, + "app": { + "bundle": "54321" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e0", + "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547", + "price": 10, + "impid": "test-imp-id", + "adm": "", + "mtype": 1 + } + ] + } + ], + "seat": "madsense" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e0", + "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547", + "price": 10, + "impid": "test-imp-id", + "adm": "", + "mtype": 1 + }, + "type": "banner" + } + ], + "seat": "madsense" + } + ] +} diff --git a/adapters/madsense/madsensetest/exemplary/banner-web.json b/adapters/madsense/madsensetest/exemplary/banner-web.json new file mode 100644 index 00000000000..0ad9c5c8960 --- /dev/null +++ b/adapters/madsense/madsensetest/exemplary/banner-web.json @@ -0,0 +1,126 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ua": "user-agent", + "ipv6": "2001:db8:3333:4444:5555:6666:7777:8888" + }, + "site": { + "domain": "domain.com", + "page": "http://domain.com/page", + "ref": "https://example.com/page" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Origin": [ + "domain.com" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "2001:db8:3333:4444:5555:6666:7777:8888" + ], + "Referer": [ + "https://example.com/page" + ] + }, + "uri": "https://test.localhost.com?company_id=9876543", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ua": "user-agent", + "ipv6": "2001:db8:3333:4444:5555:6666:7777:8888" + }, + "site": { + "domain": "domain.com", + "page": "http://domain.com/page", + "ref": "https://example.com/page" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e0", + "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547", + "price": 10, + "impid": "test-imp-id", + "adm": "", + "mtype": 1 + } + ] + } + ], + "seat": "madsense" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e0", + "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547", + "price": 10, + "impid": "test-imp-id", + "adm": "", + "mtype": 1 + }, + "type": "banner" + } + ], + "seat": "madsense" + } + ] +} diff --git a/adapters/madsense/madsensetest/exemplary/mixed-imp-types.json b/adapters/madsense/madsensetest/exemplary/mixed-imp-types.json new file mode 100644 index 00000000000..a453fd989ad --- /dev/null +++ b/adapters/madsense/madsensetest/exemplary/mixed-imp-types.json @@ -0,0 +1,312 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + }, + { + "id": "test-imp-id-2", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + }, + { + "id": "test-imp-id-3", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "site": { + "domain": "domain.com", + "page": "http://domain.com/page" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Origin": [ + "domain.com" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + }, + { + "id": "test-imp-id-2", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "site": { + "domain": "domain.com", + "page": "http://domain.com/page" + } + }, + "impIDs":["test-imp-id","test-imp-id-2"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + }, + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e801", + "impid": "test-imp-id-2", + "price": 10, + "adm": "some-test-ad-2", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 30, + "cat": [ + "IAB1-1" + ] + } + ], + "seat": "madsense" + } + ] + } + } + }, + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Origin": [ + "domain.com" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id-3", + "banner": { + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "site": { + "domain": "domain.com", + "page": "http://domain.com/page" + } + }, + "impIDs":["test-imp-id-3"] + }, + "mockResponse": { + "status": 200, + "body": { + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e2", + "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547", + "price": 10, + "impid": "test-imp-id-3", + "adm": "", + "mtype": 1 + } + ] + } + ], + "seat": "madsense" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + }, + "type": "video", + "video": { + "duration": 15, + "primary_category": "IAB1-5" + } + }, + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e801", + "impid": "test-imp-id-2", + "price": 10, + "adm": "some-test-ad-2", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 30, + "cat": [ + "IAB1-1" + ] + }, + "type": "video", + "video": { + "duration": 30, + "primary_category": "IAB1-1" + } + } + ] + }, + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "884f46aa-25ab-488a-bd7e-90e3a31a03e2", + "crid": "b83e6e58-9342-4e8c-bf6a-4ad09b231547", + "price": 10, + "impid": "test-imp-id-3", + "adm": "", + "mtype": 1 + }, + "type": "banner" + } + ] + } + ] +} + diff --git a/adapters/madsense/madsensetest/exemplary/video-app.json b/adapters/madsense/madsensetest/exemplary/video-app.json new file mode 100644 index 00000000000..d3007dc2b83 --- /dev/null +++ b/adapters/madsense/madsensetest/exemplary/video-app.json @@ -0,0 +1,141 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "app": { + "bundle": "54321" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "app": { + "bundle": "54321" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + } + ], + "seat": "madsense" + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + }, + "type": "video", + "video": { + "duration": 15, + "primary_category": "IAB1-5" + } + } + ] + } + ] +} + diff --git a/adapters/madsense/madsensetest/exemplary/video-web-pod.json b/adapters/madsense/madsensetest/exemplary/video-web-pod.json new file mode 100644 index 00000000000..ce3e354cb60 --- /dev/null +++ b/adapters/madsense/madsensetest/exemplary/video-web-pod.json @@ -0,0 +1,212 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + }, + { + "id": "test-imp-id-2", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + + ], + "site": { + "domain": "domain.com", + "page": "http://domain.com/page" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Origin": [ + "domain.com" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + }, + { + "id": "test-imp-id-2", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "site": { + "domain": "domain.com", + "page": "http://domain.com/page" + } + }, + "impIDs":["test-imp-id","test-imp-id-2"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + }, + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e801", + "impid": "test-imp-id-2", + "price": 10, + "adm": "some-test-ad-2", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 30, + "cat": [ + "IAB1-1" + ] + } + ], + "seat": "madsense" + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + }, + "type": "video", + "video": { + "duration": 15, + "primary_category": "IAB1-5" + } + }, + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e801", + "impid": "test-imp-id-2", + "price": 10, + "adm": "some-test-ad-2", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 30, + "cat": [ + "IAB1-1" + ] + }, + "type": "video", + "video": { + "duration": 30, + "primary_category": "IAB1-1" + } + } + ] + } + ] +} + diff --git a/adapters/madsense/madsensetest/exemplary/video-web.json b/adapters/madsense/madsensetest/exemplary/video-web.json new file mode 100644 index 00000000000..bf66a6470fd --- /dev/null +++ b/adapters/madsense/madsensetest/exemplary/video-web.json @@ -0,0 +1,146 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "site": { + "domain": "domain.com", + "page": "http://domain.com/page" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Origin": [ + "domain.com" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "site": { + "domain": "domain.com", + "page": "http://domain.com/page" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + } + ], + "seat": "madsense" + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + }, + "type": "video", + "video": { + "duration": 15, + "primary_category": "IAB1-5" + } + } + ] + } + ] +} + diff --git a/adapters/madsense/madsensetest/supplemental/bad-request-imp-ext-bidder.json b/adapters/madsense/madsensetest/supplemental/bad-request-imp-ext-bidder.json new file mode 100644 index 00000000000..b795e6df3c5 --- /dev/null +++ b/adapters/madsense/madsensetest/supplemental/bad-request-imp-ext-bidder.json @@ -0,0 +1,34 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": {} + } + ], + "app": { + "bundle": "54321" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [], + "expectedBidResponses": [], + "expectedMakeRequestsErrors": [ + { + "value": "Error while decoding bidderExt.Bidder", + "comparison": "startswith" + } + ] +} + diff --git a/adapters/madsense/madsensetest/supplemental/bad-request-imp-ext.json b/adapters/madsense/madsensetest/supplemental/bad-request-imp-ext.json new file mode 100644 index 00000000000..32f09afb60a --- /dev/null +++ b/adapters/madsense/madsensetest/supplemental/bad-request-imp-ext.json @@ -0,0 +1,33 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + } + } + ], + "app": { + "bundle": "54321" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [], + "expectedBidResponses": [], + "expectedMakeRequestsErrors": [ + { + "value": "Error while decoding imp.Ext", + "comparison": "startswith" + } + ] +} + diff --git a/adapters/madsense/madsensetest/supplemental/bad-response-error.json b/adapters/madsense/madsensetest/supplemental/bad-response-error.json new file mode 100644 index 00000000000..1ce30f8c3f3 --- /dev/null +++ b/adapters/madsense/madsensetest/supplemental/bad-response-error.json @@ -0,0 +1,93 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "app": { + "bundle": "54321" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "app": { + "bundle": "54321" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": "invalid response" + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Bad Server Response", + "comparison": "literal" + } + ] +} + diff --git a/adapters/madsense/madsensetest/supplemental/bad-response-mtype.json b/adapters/madsense/madsensetest/supplemental/bad-response-mtype.json new file mode 100644 index 00000000000..6c9c6c94a67 --- /dev/null +++ b/adapters/madsense/madsensetest/supplemental/bad-response-mtype.json @@ -0,0 +1,122 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "app": { + "bundle": "54321" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "app": { + "bundle": "54321" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 4, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + } + ], + "seat": "madsense" + } + ] + } + } + } + ], + "expectedBidResponses": [{ + "currency": "USD", + "bids": [] + }], + "expectedMakeBidsErrors": [ + { + "value": "MType 4 not supported", + "comparison": "literal" + } + ] +} + diff --git a/adapters/madsense/madsensetest/supplemental/bad-response-status-400.json b/adapters/madsense/madsensetest/supplemental/bad-response-status-400.json new file mode 100644 index 00000000000..87424d2f86c --- /dev/null +++ b/adapters/madsense/madsensetest/supplemental/bad-response-status-400.json @@ -0,0 +1,98 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 1920, + "h": 1080, + "mimes": [ + "video/x-flv", + "video/mp4" + ] + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ua": "user-agent", + "ip": "1.2.3.4" + }, + "site": { + "domain": "domain.com", + "page": "page.com/test" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Origin": [ + "domain.com" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "uri": "https://test.localhost.com?company_id=9876543", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "w": 1920, + "h": 1080, + "mimes": [ + "video/x-flv", + "video/mp4" + ] + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ua": "user-agent", + "ip": "1.2.3.4" + }, + "site": { + "domain": "domain.com", + "page": "page.com/test" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 400 + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/adapters/madsense/madsensetest/supplemental/bad-response-status-500.json b/adapters/madsense/madsensetest/supplemental/bad-response-status-500.json new file mode 100644 index 00000000000..143431c7144 --- /dev/null +++ b/adapters/madsense/madsensetest/supplemental/bad-response-status-500.json @@ -0,0 +1,92 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "app": { + "bundle": "54321" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "app": { + "bundle": "54321" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 500 + } + } + ], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 500. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} + diff --git a/adapters/madsense/madsensetest/supplemental/no-content-response.json b/adapters/madsense/madsensetest/supplemental/no-content-response.json new file mode 100644 index 00000000000..27caa245cd3 --- /dev/null +++ b/adapters/madsense/madsensetest/supplemental/no-content-response.json @@ -0,0 +1,87 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "app": { + "bundle": "54321" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=9876543", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "app": { + "bundle": "54321" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 204 + } + } + ], + "expectedBidResponses": [] +} + diff --git a/adapters/madsense/madsensetest/supplemental/test-response.json b/adapters/madsense/madsensetest/supplemental/test-response.json new file mode 100644 index 00000000000..9ef7c7894f4 --- /dev/null +++ b/adapters/madsense/madsensetest/supplemental/test-response.json @@ -0,0 +1,143 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "test": 1, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "app": { + "bundle": "54321" + }, + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + } + }, + "httpCalls": [ + { + "expectedRequest": { + "method": "POST", + "uri": "https://test.localhost.com?company_id=test", + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ], + "X-Openrtb-Version": [ + "2.6" + ], + "User-Agent": [ + "user-agent" + ], + "X-Forwarded-For": [ + "1.2.3.4" + ] + }, + "body": { + "id": "test-request-id", + "test": 1, + "imp": [ + { + "id": "test-imp-id", + "video": { + "mimes": [ + "video/mp4" + ], + "w": 1920, + "h": 1080 + }, + "ext": { + "bidder": { + "company_id": "9876543" + } + } + } + ], + "device": { + "ip": "1.2.3.4", + "ua": "user-agent" + }, + "app": { + "bundle": "54321" + } + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "cur": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + } + ], + "seat": "madsense" + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "8ee514f1-b2b8-4abb-89fd-084437d1e800", + "impid": "test-imp-id", + "price": 10, + "adm": "some-test-ad", + "crid": "54321", + "w": 1920, + "h": 1080, + "mtype": 2, + "dur": 15, + "cat": [ + "IAB1-5", + "IAB1-6" + ] + }, + "type": "video", + "video": { + "duration": 15, + "primary_category": "IAB1-5" + } + } + ] + } + ] +} + diff --git a/adapters/madsense/params_test.go b/adapters/madsense/params_test.go new file mode 100644 index 00000000000..de597067458 --- /dev/null +++ b/adapters/madsense/params_test.go @@ -0,0 +1,51 @@ +package madsense + +import ( + "encoding/json" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/stretchr/testify/require" + "testing" +) + +// This file actually intends to test static/bidder-params/madsense.json +// +// These also validate the format of the external API: request.imp[i].ext.prebid.bidder.madsense + +// TestValidParams makes sure that the madsense schema accepts all imp.ext fields which we intend to support. +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + require.NoError(t, err, "Failed to fetch the json-schemas") + + for _, validParam := range validParams { + err := validator.Validate(openrtb_ext.BidderMadSense, json.RawMessage(validParam)) + require.NoError(t, err, "Schema rejected madsense params: %s", validParam) + } +} + +// TestInvalidParams makes sure that the madsense schema rejects all the imp.ext fields we don't support. +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + require.NoError(t, err, "Failed to fetch the json-schemas") + + for _, invalidParam := range invalidParams { + err := validator.Validate(openrtb_ext.BidderMadSense, json.RawMessage(invalidParam)) + require.Error(t, err, "Schema allowed unexpected params: %s", invalidParam) + } +} + +var validParams = []string{ + `{"company_id": "9876543"}`, +} + +var invalidParams = []string{ + ``, + `null`, + `true`, + `5`, + `4.2`, + `[]`, + `{}`, + `{"companyId": "987654a"}`, + `{"companyId": "98765432"}`, + `{"company_id": ""}`, +} diff --git a/adapters/madsense/utils.go b/adapters/madsense/utils.go new file mode 100644 index 00000000000..992d136330c --- /dev/null +++ b/adapters/madsense/utils.go @@ -0,0 +1,99 @@ +package madsense + +import ( + "fmt" + "net/http" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/errortypes" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" +) + +func parseImpExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpMadSense, error) { + var bidderExt adapters.ExtImpBidder + + if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { + return nil, &errortypes.BadInput{ + Message: fmt.Sprintf("Error while decoding imp.Ext, err: %v", err), + } + } + + ext := openrtb_ext.ExtImpMadSense{} + err := jsonutil.Unmarshal(bidderExt.Bidder, &ext) + if err != nil { + return nil, &errortypes.BadInput{ + Message: fmt.Sprintf("Error while decoding bidderExt.Bidder, err: %v", err), + } + } + + return &ext, nil +} + +func getHeaders(request *openrtb2.BidRequest) http.Header { + headers := http.Header{} + headers.Set("Content-Type", "application/json;charset=utf-8") + headers.Set("Accept", "application/json") + headers.Set("X-Openrtb-Version", "2.6") + + if request.Device != nil { + if len(request.Device.UA) > 0 { + headers.Set("User-Agent", request.Device.UA) + } + + if len(request.Device.IP) > 0 { + headers.Set("X-Forwarded-For", request.Device.IP) + } + + if len(request.Device.IPv6) > 0 { + headers.Set("X-Forwarded-For", request.Device.IPv6) + } + } + + if request.Site != nil { + if request.Site.Domain != "" { + headers.Set("Origin", request.Site.Domain) + } + if request.Site.Ref != "" { + headers.Set("Referer", request.Site.Ref) + } + } + return headers +} + +func getTypedBidFromBid(bid *openrtb2.Bid) (*adapters.TypedBid, error) { + bidType, err := getMediaTypeForBid(bid) + if err != nil { + return nil, err + } + + var bidVideo *openrtb_ext.ExtBidPrebidVideo + if bidType == openrtb_ext.BidTypeVideo { + bidVideo = &openrtb_ext.ExtBidPrebidVideo{} + if len(bid.Cat) > 0 { + bidVideo.PrimaryCategory = bid.Cat[0] + } + if bid.Dur > 0 { + bidVideo.Duration = int(bid.Dur) + } + } + return &adapters.TypedBid{ + Bid: bid, + BidType: bidType, + BidVideo: bidVideo, + }, nil +} + +func getMediaTypeForBid(bid *openrtb2.Bid) (openrtb_ext.BidType, error) { + switch bid.MType { + case openrtb2.MarkupBanner: + return openrtb_ext.BidTypeBanner, nil + case openrtb2.MarkupVideo: + return openrtb_ext.BidTypeVideo, nil + default: + return "", &errortypes.BadServerResponse{ + Message: fmt.Sprintf("MType %v not supported", bid.MType), + } + } +} diff --git a/adapters/mobkoi/mobkoi.go b/adapters/mobkoi/mobkoi.go new file mode 100644 index 00000000000..19a6d34d52c --- /dev/null +++ b/adapters/mobkoi/mobkoi.go @@ -0,0 +1,121 @@ +package mobkoi + +import ( + "errors" + "net/http" + "net/url" + "strings" + + "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/prebid/prebid-server/v3/util/jsonutil" +) + +type adapter struct { + endpoint string +} + +type BidderExt struct { + Bidder openrtb_ext.ImpExtMobkoi `json:"bidder"` +} + +type UserExt struct { + Consent string `json:"consent"` +} + +// Builder builds a new instance of the {bidder} adapter for the given bidder with the given config. +func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + bidder := &adapter{ + endpoint: config.Endpoint, + } + return bidder, nil +} + +func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { + ext := BidderExt{} + if err := jsonutil.Unmarshal(request.Imp[0].Ext, &ext); err != nil { + return nil, []error{err} + } + + if request.Imp[0].TagID == "" { + if ext.Bidder.PlacementID != "" { + request.Imp[0].TagID = ext.Bidder.PlacementID + } else { + return nil, []error{ + errors.New("invalid because it comes with neither request.imp[0].tagId nor req.imp[0].ext.Bidder.placementId"), + } + } + } + + uri := a.endpoint + if ext.Bidder.AdServerBaseUrl != "" { + baseURL, err := url.ParseRequestURI(ext.Bidder.AdServerBaseUrl) + if err == nil { // Ensure parsing doesn't fail + baseURL.Path = strings.TrimRight(baseURL.Path, "/") + "/bid" + uri = baseURL.String() + } + } + + if request.User != nil && request.User.Consent != "" { + user := *request.User + userExt, err := jsonutil.Marshal(UserExt{ + Consent: user.Consent, + }) + if err != nil { + return nil, []error{err} + } + user.Ext = userExt + request.User = &user + } + + requestJSON, err := jsonutil.Marshal(request) + if err != nil { + return nil, []error{err} + } + + headers := http.Header{} + headers.Add("Content-Type", "application/json") + headers.Add("Accept", "application/json") + + requestData := &adapters.RequestData{ + Method: http.MethodPost, + Uri: uri, + Body: requestJSON, + Headers: headers, + ImpIDs: openrtb_ext.GetImpIDs(request.Imp), + } + + return []*adapters.RequestData{requestData}, nil +} + +func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { + if adapters.IsResponseStatusCodeNoContent(responseData) { + return nil, nil + } + + if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil { + return nil, []error{err} + } + + var response openrtb2.BidResponse + if err := jsonutil.Unmarshal(responseData.Body, &response); err != nil { + return nil, []error{err} + } + + bidResponse := adapters.NewBidderResponseWithBidsCapacity(1) + bidResponse.Currency = response.Cur + + for _, seatBid := range response.SeatBid { + for i := range seatBid.Bid { + bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ + Bid: &seatBid.Bid[i], + BidType: openrtb_ext.BidTypeBanner, + Seat: "mobkoi", + }) + + } + } + return bidResponse, nil +} diff --git a/adapters/mobkoi/mobkoi_test.go b/adapters/mobkoi/mobkoi_test.go new file mode 100644 index 00000000000..36ee6a329c0 --- /dev/null +++ b/adapters/mobkoi/mobkoi_test.go @@ -0,0 +1,21 @@ +package mobkoi + +import ( + "testing" + + "github.com/prebid/prebid-server/v3/adapters/adapterstest" + "github.com/prebid/prebid-server/v3/config" + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestJsonSamples(t *testing.T) { + bidder, buildErr := Builder(openrtb_ext.BidderMobkoi, config.Adapter{ + Endpoint: "http://any.url"}, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + if buildErr != nil { + t.Fatalf("Builder returned unexpected error %v", buildErr) + } + + adapterstest.RunJSONBidderTest(t, "mobkoitest", bidder) +} diff --git a/adapters/mobkoi/mobkoitest/exemplary/banner-web.json b/adapters/mobkoi/mobkoitest/exemplary/banner-web.json new file mode 100644 index 00000000000..45c33e215b8 --- /dev/null +++ b/adapters/mobkoi/mobkoitest/exemplary/banner-web.json @@ -0,0 +1,148 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ], + "Accept": [ + "application/json" + ] + }, + "uri": "http://dev.mobkoi.com/bid", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "placementId", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string", + "ext": { + "consent": "consent-string" + } + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "awesome-resp-id", + "seatbid": [ + { + "bid": [ + { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "lurl": "mobkoi/loss", + "nurl": "mobkoi/win" + } + ], + "type": "banner", + "seat": "mobkoi" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "crid": "20", + "adomain": [ + "awesome.com" + ], + "w": 320, + "h": 50, + "lurl": "mobkoi/loss", + "nurl": "mobkoi/win" + }, + "type": "banner", + "seat": "mobkoi" + } + ] + } + ] +} diff --git a/adapters/mobkoi/mobkoitest/exemplary/fallback-uri.json b/adapters/mobkoi/mobkoitest/exemplary/fallback-uri.json new file mode 100644 index 00000000000..6f40bcd2e38 --- /dev/null +++ b/adapters/mobkoi/mobkoitest/exemplary/fallback-uri.json @@ -0,0 +1,148 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "invalid" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ], + "Accept": [ + "application/json" + ] + }, + "uri": "http://any.url", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "placementId", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "invalid" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string", + "ext": { + "consent": "consent-string" + } + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "awesome-resp-id", + "seatbid": [ + { + "bid": [ + { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "lurl": "mobkoi/loss", + "nurl": "mobkoi/win" + } + ], + "type": "banner", + "seat": "mobkoi" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "crid": "20", + "adomain": [ + "awesome.com" + ], + "w": 320, + "h": 50, + "lurl": "mobkoi/loss", + "nurl": "mobkoi/win" + }, + "type": "banner", + "seat": "mobkoi" + } + ] + } + ] +} diff --git a/adapters/mobkoi/mobkoitest/exemplary/use-tag-id.json b/adapters/mobkoi/mobkoitest/exemplary/use-tag-id.json new file mode 100644 index 00000000000..cc26ab0cd10 --- /dev/null +++ b/adapters/mobkoi/mobkoitest/exemplary/use-tag-id.json @@ -0,0 +1,146 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "tagId", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ], + "Accept": [ + "application/json" + ] + }, + "uri": "http://dev.mobkoi.com/bid", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "tagId", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string", + "ext": { + "consent": "consent-string" + } + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "awesome-resp-id", + "seatbid": [ + { + "bid": [ + { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "adomain": [ + "awesome.com" + ], + "crid": "20", + "w": 320, + "h": 50, + "lurl": "mobkoi/loss", + "nurl": "mobkoi/win" + } + ], + "type": "banner", + "seat": "mobkoi" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "bids": [ + { + "bid": { + "id": "a3ae1b4e2fc24a4fb45540082e98e161", + "impid": "some-impression-id1", + "price": 3.5, + "adm": "awesome-markup", + "crid": "20", + "adomain": [ + "awesome.com" + ], + "w": 320, + "h": 50, + "lurl": "mobkoi/loss", + "nurl": "mobkoi/win" + }, + "type": "banner", + "seat": "mobkoi" + } + ] + } + ] +} diff --git a/adapters/mobkoi/mobkoitest/supplemental/bad-imp-ext.json b/adapters/mobkoi/mobkoitest/supplemental/bad-imp-ext.json new file mode 100644 index 00000000000..f9ceba76491 --- /dev/null +++ b/adapters/mobkoi/mobkoitest/supplemental/bad-imp-ext.json @@ -0,0 +1,41 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "", + "banner": { + "w": 320, + "h": 50 + }, + "ext": [] + } + ] + }, + "httpCalls": [], + "expectedBidResponses": [], + "expectedMakeRequestsErrors": [ + { + "value": "expect { or n, but found [", + "comparison": "literal" + } + ] +} diff --git a/adapters/mobkoi/mobkoitest/supplemental/bad-input.json b/adapters/mobkoi/mobkoitest/supplemental/bad-input.json new file mode 100644 index 00000000000..cac08d4bbfd --- /dev/null +++ b/adapters/mobkoi/mobkoitest/supplemental/bad-input.json @@ -0,0 +1,108 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ], + "Accept": [ + "application/json" + ] + }, + "uri": "http://dev.mobkoi.com/bid", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "placementId", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string", + "ext": { + "consent": "consent-string" + } + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1" + ] + }, + "mockResponse": { + "status": 400, + "body": { + "message": "irrelevant" + } + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 400. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/adapters/mobkoi/mobkoitest/supplemental/bad-response.json b/adapters/mobkoi/mobkoitest/supplemental/bad-response.json new file mode 100644 index 00000000000..4d872c212d6 --- /dev/null +++ b/adapters/mobkoi/mobkoitest/supplemental/bad-response.json @@ -0,0 +1,116 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ], + "Accept": [ + "application/json" + ] + }, + "uri": "http://dev.mobkoi.com/bid", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "placementId", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string", + "ext": { + "consent": "consent-string" + } + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1" + ] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "awesome-resp-id", + "seatbid": [ + { + "bid": {}, + "type": "banner", + "seat": "mobkoi" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "cannot unmarshal .*", + "comparison": "regex" + } + ] +} diff --git a/adapters/mobkoi/mobkoitest/supplemental/no-content.json b/adapters/mobkoi/mobkoitest/supplemental/no-content.json new file mode 100644 index 00000000000..e645bb079b4 --- /dev/null +++ b/adapters/mobkoi/mobkoitest/supplemental/no-content.json @@ -0,0 +1,99 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ], + "Accept": [ + "application/json" + ] + }, + "uri": "http://dev.mobkoi.com/bid", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "placementId", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string", + "ext": { + "consent": "consent-string" + } + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1" + ] + }, + "mockResponse": { + "status": 204 + } + } + ], + "expectedBidResponses": [] +} diff --git a/adapters/mobkoi/mobkoitest/supplemental/no-tag-nor-placement-id.json b/adapters/mobkoi/mobkoitest/supplemental/no-tag-nor-placement-id.json new file mode 100644 index 00000000000..a3c943f3a07 --- /dev/null +++ b/adapters/mobkoi/mobkoitest/supplemental/no-tag-nor-placement-id.json @@ -0,0 +1,45 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ] + }, + "httpCalls": [], + "expectedBidResponses": [], + "expectedMakeRequestsErrors": [ + { + "value": "invalid because it comes with neither request.imp[0].tagId nor req.imp[0].ext.Bidder.placementId", + "comparison": "literal" + } + ] +} diff --git a/adapters/mobkoi/mobkoitest/supplemental/server-error.json b/adapters/mobkoi/mobkoitest/supplemental/server-error.json new file mode 100644 index 00000000000..c21b37863c8 --- /dev/null +++ b/adapters/mobkoi/mobkoitest/supplemental/server-error.json @@ -0,0 +1,108 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "tmax": 1000, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string" + }, + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Content-Type": [ + "application/json" + ], + "Accept": [ + "application/json" + ] + }, + "uri": "http://dev.mobkoi.com/bid", + "body": { + "id": "some-request-id", + "device": { + "ua": "test-user-agent", + "ip": "123.123.123.123", + "language": "en", + "dnt": 0 + }, + "imp": [ + { + "id": "some-impression-id1", + "tagid": "placementId", + "banner": { + "w": 320, + "h": 50 + }, + "ext": { + "bidder": { + "placementId": "placementId", + "adServerBaseUrl": "http://dev.mobkoi.com" + } + } + } + ], + "site": { + "page": "test.com", + "publisher": { + "id": "123456789" + } + }, + "user": { + "buyeruid": "awesome-user", + "consent": "consent-string", + "ext": { + "consent": "consent-string" + } + }, + "tmax": 1000 + }, + "impIDs": [ + "some-impression-id1" + ] + }, + "mockResponse": { + "status": 500, + "body": { + "message": "irrelevant" + } + } + } + ], + "expectedBidResponses": [], + "expectedMakeBidsErrors": [ + { + "value": "Unexpected status code: 500. Run with request.debug = 1 for more info", + "comparison": "literal" + } + ] +} diff --git a/adapters/mobkoi/params_test.go b/adapters/mobkoi/params_test.go new file mode 100644 index 00000000000..1ee1fd97798 --- /dev/null +++ b/adapters/mobkoi/params_test.go @@ -0,0 +1,63 @@ +package mobkoi + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestValidParams(test *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + + if err != nil { + test.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, validParam := range validParams { + err := validator.Validate(openrtb_ext.BidderMobkoi, json.RawMessage(validParam)) + + if err != nil { + test.Errorf("Schema rejected Mobkoi params: %s\nError: %v", validParam, err) + } + } +} + +func TestInvalidParams(test *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + + if err != nil { + test.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, invalidParam := range invalidParams { + err := validator.Validate(openrtb_ext.BidderMobkoi, json.RawMessage(invalidParam)) + + if err == nil { + test.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{}`, + `{"foo":"bar"}`, + `{"placementId":"abc"}`, + `{"placementId":"abc", "adServerBaseUrl":"https://adserver.mobkoi.com"}`, + `{"adServerBaseUrl":"http://dev.mobkoi.com"}`, + `{"placementId":"abc", "adServerBaseUrl":"https://adserver.mobkoi.com"}`, +} + +var invalidParams = []string{ + ``, + `null`, + `true`, + `1`, + `1.0`, + `[]`, + `{"placementId":123, "adServerBaseUrl":"mobkoi.com"}`, + `{"placementId":"abc", "adServerBaseUrl":"https://ikea.ad.com"}`, + `{"placementId":"abc", "adServerBaseUrl":"http://ikea.ad.com"}`, + `{"placementId":"abc", "adServerBaseUrl":"https://adserver.mobkoi.net"}`, + `{"placementId":"abc", "adServerBaseUrl":"https://mobkoi.com"}`, +} diff --git a/adapters/openx/openx.go b/adapters/openx/openx.go index 11b5268b9bf..f10985f3085 100644 --- a/adapters/openx/openx.go +++ b/adapters/openx/openx.go @@ -236,7 +236,7 @@ func (a *OpenxAdapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRe for i := range sb.Bid { bidResponse.Bids = append(bidResponse.Bids, &adapters.TypedBid{ Bid: &sb.Bid[i], - BidType: getMediaTypeForImp(sb.Bid[i].ImpID, internalRequest.Imp), + BidType: getBidType(sb.Bid[i].MType, sb.Bid[i].ImpID, internalRequest.Imp), BidVideo: getBidVideo(&sb.Bid[i]), }) } @@ -255,6 +255,19 @@ func getBidVideo(bid *openrtb2.Bid) *openrtb_ext.ExtBidPrebidVideo { } } +func getBidType(mtype openrtb2.MarkupType, impId string, imps []openrtb2.Imp) openrtb_ext.BidType { + switch mtype { + case openrtb2.MarkupBanner: + return openrtb_ext.BidTypeBanner + case openrtb2.MarkupVideo: + return openrtb_ext.BidTypeVideo + case openrtb2.MarkupNative: + return openrtb_ext.BidTypeNative + default: + return getMediaTypeForImp(impId, imps) + } +} + // getMediaTypeForImp figures out which media type this bid is for. // // OpenX doesn't support multi-type impressions. diff --git a/adapters/openx/openxtest/exemplary/fledge.json b/adapters/openx/openxtest/exemplary/fledge.json index 256408eb850..dc559d3a0be 100644 --- a/adapters/openx/openxtest/exemplary/fledge.json +++ b/adapters/openx/openxtest/exemplary/fledge.json @@ -57,7 +57,8 @@ "adm": "some-test-ad", "crid": "crid_10", "h": 90, - "w": 728 + "w": 728, + "mtype": 1 }] } ], @@ -91,7 +92,8 @@ "adm": "some-test-ad", "crid": "crid_10", "w": 728, - "h": 90 + "h": 90, + "mtype": 1 }, "type": "banner" } diff --git a/adapters/openx/openxtest/exemplary/simple-banner.json b/adapters/openx/openxtest/exemplary/simple-banner.json index aa9f9476dcf..59d540ebc4a 100644 --- a/adapters/openx/openxtest/exemplary/simple-banner.json +++ b/adapters/openx/openxtest/exemplary/simple-banner.json @@ -53,7 +53,8 @@ "adm": "{\"ver\": \"1.2\", \"assets\": [{\"id\": 1, \"required\": 1,\"title\": {\"text\": \"OpenX (Title)\"}}], \"link\": {\"url\": \"https://www.openx.com/\"}, \"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"http://example.com/impression\"}]}", "crid": "crid_10", "h": 90, - "w": 728 + "w": 728, + "mtype": 1 }] } ], @@ -75,7 +76,8 @@ "adm": "{\"ver\": \"1.2\", \"assets\": [{\"id\": 1, \"required\": 1,\"title\": {\"text\": \"OpenX (Title)\"}}], \"link\": {\"url\": \"https://www.openx.com/\"}, \"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"http://example.com/impression\"}]}", "crid": "crid_10", "w": 728, - "h": 90 + "h": 90, + "mtype": 1 }, "type": "banner" } diff --git a/adapters/openx/openxtest/exemplary/simple-native.json b/adapters/openx/openxtest/exemplary/simple-native.json index e9975b0b182..a7add01ba11 100644 --- a/adapters/openx/openxtest/exemplary/simple-native.json +++ b/adapters/openx/openxtest/exemplary/simple-native.json @@ -56,7 +56,8 @@ "adm": "{\"ver\": \"1.2\", \"assets\": [{\"id\": 1, \"required\": 1,\"title\": {\"text\": \"OpenX (Title)\"}}], \"link\": {\"url\": \"https://www.openx.com/\"}, \"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"http://example.com/impression\"}]}", "crid": "crid_10", "w": 300, - "h": 200 + "h": 200, + "mtype": 4 }] } ] @@ -77,11 +78,12 @@ "adm": "{\"ver\": \"1.2\", \"assets\": [{\"id\": 1, \"required\": 1,\"title\": {\"text\": \"OpenX (Title)\"}}], \"link\": {\"url\": \"https://www.openx.com/\"}, \"eventtrackers\":[{\"event\":1,\"method\":1,\"url\":\"http://example.com/impression\"}]}", "crid": "crid_10", "w": 300, - "h": 200 + "h": 200, + "mtype": 4 }, "type": "native" } ] } ] -} \ No newline at end of file +} diff --git a/adapters/openx/openxtest/exemplary/simple-video.json b/adapters/openx/openxtest/exemplary/simple-video.json index e6b67775999..19beb1ae7db 100644 --- a/adapters/openx/openxtest/exemplary/simple-video.json +++ b/adapters/openx/openxtest/exemplary/simple-video.json @@ -63,7 +63,8 @@ "h": 576, "cattax": 1, "cat": ["IAB20"], - "dur": 30 + "dur": 30, + "mtype": 2 }] } ] @@ -88,7 +89,8 @@ "h": 576, "cattax": 1, "cat": ["IAB20"], - "dur": 30 + "dur": 30, + "mtype": 2 }, "video": { "duration": 30, diff --git a/adapters/openx/openxtest/exemplary/video-rewarded.json b/adapters/openx/openxtest/exemplary/video-rewarded.json index 58eadd7df9f..eb51e10debf 100644 --- a/adapters/openx/openxtest/exemplary/video-rewarded.json +++ b/adapters/openx/openxtest/exemplary/video-rewarded.json @@ -70,7 +70,8 @@ "adm": "some-test-ad", "crid": "crid_10", "w": 1024, - "h": 576 + "h": 576, + "mtype": 2 }] } ] @@ -92,7 +93,8 @@ "adm": "some-test-ad", "crid": "crid_10", "w": 1024, - "h": 576 + "h": 576, + "mtype": 2 }, "type": "video" } diff --git a/adapters/openx/openxtest/supplemental/missing-mtype.json b/adapters/openx/openxtest/supplemental/missing-mtype.json new file mode 100644 index 00000000000..69fec729ef9 --- /dev/null +++ b/adapters/openx/openxtest/supplemental/missing-mtype.json @@ -0,0 +1,312 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "id": "banner-imp-1", + "banner": {}, + "ext": { + "bidder": { + "unit": "111", + "delDomain": "se-demo-d.openx.net" + } + } + }, + { + "id": "video-imp-1", + "video": {"mimes": ["video/mp4"]}, + "ext": { + "bidder": { + "unit": "333", + "delDomain": "se-demo-d.openx.net" + } + } + }, + { + "id": "native-imp-1", + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":90}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "unit": "666", + "delDomain": "se-demo-d.openx.net" + } + } + }, + { + "id": "banner-native-imp-1", + "banner": {}, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":90}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "unit": "777", + "delDomain": "se-demo-d.openx.net" + } + } + }, + { + "id": "video-native-imp-1", + "video": {"mimes": ["video/mp4"]}, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":90}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "unit": "888", + "delDomain": "se-demo-d.openx.net" + } + } + }, + { + "id": "multi-type-imp", + "banner": {}, + "video": {"mimes": ["video/mp4"]}, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":90}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}]}", + "ver": "1.2" + }, + "ext": { + "bidder": { + "unit": "555", + "delDomain": "se-demo-d.openx.net" + } + } + } + ] + }, + + "httpCalls": [ + { + "expectedRequest": { + "uri": "http://rtb.openx.net/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "banner-imp-1", + "banner": {}, + "tagid": "111" + }, + { + "id": "native-imp-1", + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":90}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}]}", + "ver": "1.2" + }, + "tagid": "666" + }, + { + "id": "banner-native-imp-1", + "banner": {}, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":90}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}]}", + "ver": "1.2" + }, + "tagid": "777" + }, + { + "id": "multi-type-imp", + "banner": {}, + "video": {"mimes": ["video/mp4"]}, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":90}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}]}", + "ver": "1.2" + }, + "tagid": "555" + } + ], + "ext": { + "bc": "hb_pbs_1.0.0", + "delDomain": "se-demo-d.openx.net" + } + }, + "impIDs":["banner-imp-1","native-imp-1","banner-native-imp-1","multi-type-imp"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "openx", + "bid": [ + { + "id": "banner-bid-1", + "impid": "banner-imp-1", + "price": 0.1 + }, + { + "id": "native-bid-1", + "impid": "native-imp-1", + "price": 0.1 + }, + { + "id": "banner-native-bid-1", + "impid": "banner-native-imp-1", + "price": 0 + }, + { + "id": "multi-type-bid", + "impid": "multi-type-imp", + "price": 0 + } + ] + } + ] + } + } + }, + { + "expectedRequest": { + "uri": "http://rtb.openx.net/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "video-imp-1", + "video": {"mimes": ["video/mp4"]}, + "tagid": "333" + } + ], + "ext": { + "bc": "hb_pbs_1.0.0", + "delDomain": "se-demo-d.openx.net" + } + }, + "impIDs":["video-imp-1"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "openx", + "bid": [ + { + "id": "video-bid-1", + "impid": "video-imp-1", + "price": 0.1 + } + ] + } + ] + } + } + }, + { + "expectedRequest": { + "uri": "http://rtb.openx.net/prebid", + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "video-native-imp-1", + "video": {"mimes": ["video/mp4"]}, + "native": { + "request": "{\"ver\":\"1.2\",\"assets\":[{\"id\":1,\"required\":1,\"title\":{\"len\":90}},{\"id\":2,\"required\":1,\"img\":{\"type\":3,\"wmin\":1200,\"hmin\":627}}],\"eventtrackers\":[{\"event\":1,\"methods\":[1,2]}]}", + "ver": "1.2" + }, + "tagid": "888" + } + ], + "ext": { + "bc": "hb_pbs_1.0.0", + "delDomain": "se-demo-d.openx.net" + } + }, + "impIDs":["video-native-imp-1"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-request-id", + "seatbid": [ + { + "seat": "openx", + "bid": [ + { + "id": "video-native-bid-1", + "impid": "video-native-imp-1", + "price": 0.0 + } + ] + } + ] + } + } + } + ], + + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "banner-bid-1", + "impid": "banner-imp-1", + "price": 0.1 + }, + "type": "banner" + }, + { + "bid": { + "id": "native-bid-1", + "impid": "native-imp-1", + "price": 0.1 + }, + "type": "native" + }, + { + "bid": { + "id": "banner-native-bid-1", + "impid": "banner-native-imp-1", + "price": 0 + }, + "type": "banner" + }, + { + "bid": { + "id": "multi-type-bid", + "impid": "multi-type-imp", + "price": 0 + }, + "type": "banner" + } + ] + }, + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "video-bid-1", + "impid": "video-imp-1", + "price": 0.1 + }, + "type": "video" + } + ] + }, + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "video-native-bid-1", + "impid": "video-native-imp-1", + "price": 0.0 + }, + "type": "video" + } + ] + } + ] +} diff --git a/adapters/openx/openxtest/supplemental/multi-imp.json b/adapters/openx/openxtest/supplemental/multi-imp.json index a8c9be59513..6d20a5ea89b 100644 --- a/adapters/openx/openxtest/supplemental/multi-imp.json +++ b/adapters/openx/openxtest/supplemental/multi-imp.json @@ -164,27 +164,32 @@ { "id": "banner-bid-1", "impid": "banner-imp-1", - "price": 0.1 + "price": 0.1, + "mtype": 1 }, { "id": "native-bid-1", "impid": "native-imp-1", - "price": 0.1 + "price": 0.1, + "mtype": 4 }, { "id": "banner-bid-2", "impid": "banner-imp-2", - "price": 0.2 + "price": 0.2, + "mtype": 1 }, { "id": "banner-native-bid-1", "impid": "banner-native-imp-1", - "price": 0 + "price": 0, + "mtype": 4 }, { "id": "multi-type-bid", "impid": "multi-type-imp", - "price": 0 + "price": 0, + "mtype": 2 } ] } @@ -222,7 +227,8 @@ { "id": "video-bid-1", "impid": "video-imp-1", - "price": 0.1 + "price": 0.1, + "mtype": 2 } ] } @@ -266,7 +272,8 @@ { "id": "video-bid-2", "impid": "video-imp-2", - "price": 0.2 + "price": 0.2, + "mtype": 2 } ] } @@ -308,7 +315,8 @@ { "id": "video-native-bid-1", "impid": "video-native-imp-1", - "price": 0.0 + "price": 0.0, + "mtype": 4 } ] } @@ -326,7 +334,8 @@ "bid": { "id": "banner-bid-1", "impid": "banner-imp-1", - "price": 0.1 + "price": 0.1, + "mtype": 1 }, "type": "banner" }, @@ -334,7 +343,8 @@ "bid": { "id": "native-bid-1", "impid": "native-imp-1", - "price": 0.1 + "price": 0.1, + "mtype": 4 }, "type": "native" }, @@ -342,7 +352,8 @@ "bid": { "id": "banner-bid-2", "impid": "banner-imp-2", - "price": 0.2 + "price": 0.2, + "mtype": 1 }, "type": "banner" }, @@ -350,17 +361,19 @@ "bid": { "id": "banner-native-bid-1", "impid": "banner-native-imp-1", - "price": 0 + "price": 0, + "mtype": 4 }, - "type": "banner" + "type": "native" }, { "bid": { "id": "multi-type-bid", "impid": "multi-type-imp", - "price": 0 + "price": 0, + "mtype": 2 }, - "type": "banner" + "type": "video" } ] }, @@ -371,7 +384,8 @@ "bid": { "id": "video-bid-1", "impid": "video-imp-1", - "price": 0.1 + "price": 0.1, + "mtype": 2 }, "type": "video" } @@ -384,7 +398,8 @@ "bid": { "id": "video-bid-2", "impid": "video-imp-2", - "price": 0.2 + "price": 0.2, + "mtype": 2 }, "type": "video" } @@ -397,9 +412,10 @@ "bid": { "id": "video-native-bid-1", "impid": "video-native-imp-1", - "price": 0.0 + "price": 0.0, + "mtype": 4 }, - "type": "video" + "type": "native" } ] } diff --git a/adapters/relevantdigital/relevantdigital.go b/adapters/relevantdigital/relevantdigital.go index 35789f3b841..702dca6b271 100644 --- a/adapters/relevantdigital/relevantdigital.go +++ b/adapters/relevantdigital/relevantdigital.go @@ -16,7 +16,7 @@ import ( "github.com/prebid/prebid-server/v3/macros" "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/prebid/prebid-server/v3/util/jsonutil" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" ) type adapter struct { diff --git a/adapters/thetradedesk/params_test.go b/adapters/thetradedesk/params_test.go index 05febe45fab..b0829fb290c 100644 --- a/adapters/thetradedesk/params_test.go +++ b/adapters/thetradedesk/params_test.go @@ -35,9 +35,9 @@ func TestInvalidParams(t *testing.T) { } var validParams = []string{ - `{"publisherId": "123456"}`, - `{"publisherId": "pub-123456"}`, - `{"publisherId": "publisherIDAllString"}`, + `{"publisherId": "123456", "supplySourceId": "xyz_123"}`, + `{"publisherId": "pub-123456", "supplySourceId": "direct_123"}`, + `{"publisherId": "publisherIDAllString", "supplySourceId": "direct123"}`, } var invalidParams = []string{ @@ -48,6 +48,6 @@ var invalidParams = []string{ `4.2`, `[]`, `{}`, - `{"publisherId": 123456}`, - `{"publisherId": 0}`, + `{"publisherId": 123456, "supplySourceId": 123}`, + `{"publisherId": 0, "supplySourceId": 0}`, } diff --git a/adapters/thetradedesk/thetradedesk.go b/adapters/thetradedesk/thetradedesk.go index 0288b4bb097..47fb9ee0fde 100644 --- a/adapters/thetradedesk/thetradedesk.go +++ b/adapters/thetradedesk/thetradedesk.go @@ -17,18 +17,16 @@ import ( "github.com/prebid/openrtb/v20/openrtb2" ) -const PREBID_INTEGRATION_TYPE = "1" +//const PREBID_INTEGRATION_TYPE = "1" type adapter struct { - bidderEndpoint string -} - -type ExtImpBidderTheTradeDesk struct { - adapters.ExtImpBidder + bidderEndpointTemplate string + defaultEndpoint string + templateEndpoint *template.Template } func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { - pubID, err := getPublisherId(request.Imp) + pubID, supplySourceId, err := getExtensionInfo(request.Imp) if err != nil { return nil, []error{err} @@ -87,37 +85,74 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.E return nil, errs } + bidderEndpoint, err := a.buildEndpointURL(supplySourceId) + if err != nil { + return nil, []error{errors.New("Failed to build endpoint URL")} + } + headers := http.Header{} headers.Add("Content-Type", "application/json;charset=utf-8") headers.Add("Accept", "application/json") - headers.Add("x-integration-type", PREBID_INTEGRATION_TYPE) + //headers.Add("x-integration-type", PREBID_INTEGRATION_TYPE) this will be parsed and added conditionally later return []*adapters.RequestData{{ Method: "POST", - Uri: a.bidderEndpoint, + Uri: bidderEndpoint, Body: reqJSON, Headers: headers, ImpIDs: openrtb_ext.GetImpIDs(request.Imp), }}, errs } -func getPublisherId(impressions []openrtb2.Imp) (string, error) { +func (a *adapter) buildEndpointURL(supplySourceId string) (string, error) { + if supplySourceId == "" { + return a.defaultEndpoint, nil + } + + urlParams := macros.EndpointTemplateParams{SupplyId: supplySourceId} + bidderEndpoint, err := macros.ResolveMacros(a.templateEndpoint, urlParams) + + if err != nil { + return "", fmt.Errorf("unable to resolve endpoint macros: %v", err) + } + + return bidderEndpoint, nil +} + +func getExtensionInfo(impressions []openrtb2.Imp) (string, string, error) { + publisherId := "" + supplySourceId := "" for _, imp := range impressions { + var ttdExt, err = getImpressionExt(&imp) + if err != nil { + return "", "", err + } - var bidderExt ExtImpBidderTheTradeDesk - if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { - return "", err + if ttdExt.PublisherId != "" && publisherId == "" { + publisherId = ttdExt.PublisherId } - var ttdExt openrtb_ext.ExtImpTheTradeDesk - if err := jsonutil.Unmarshal(bidderExt.Bidder, &ttdExt); err != nil { - return "", err + if ttdExt.SupplySourceId != "" && supplySourceId == "" { + supplySourceId = ttdExt.SupplySourceId } - if ttdExt.PublisherId != "" { - return ttdExt.PublisherId, nil + if publisherId != "" && supplySourceId != "" { + break } } - return "", nil + return publisherId, supplySourceId, nil +} + +func getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ExtImpTheTradeDesk, error) { + var bidderExt adapters.ExtImpBidder + if err := jsonutil.Unmarshal(imp.Ext, &bidderExt); err != nil { + return nil, err + } + + var ttdExt openrtb_ext.ExtImpTheTradeDesk + if err := jsonutil.Unmarshal(bidderExt.Bidder, &ttdExt); err != nil { + return nil, err + } + return &ttdExt, nil } func (a *adapter) MakeBids(internalRequest *openrtb2.BidRequest, externalRequest *adapters.RequestData, response *adapters.ResponseData) (*adapters.BidderResponse, []error) { @@ -172,11 +207,6 @@ func getBidType(markupType openrtb2.MarkupType) (openrtb_ext.BidType, error) { } func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { - template, err := template.New("endpointTemplate").Parse(config.Endpoint) - if err != nil { - return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) - } - if len(config.ExtraAdapterInfo) > 0 { isValidEndpoint, err := regexp.Match("([a-z]+)$", []byte(config.ExtraAdapterInfo)) if !isValidEndpoint || err != nil { @@ -184,14 +214,21 @@ func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server co } } + template, err := template.New("endpointTemplate").Parse(config.Endpoint) + if err != nil { + return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) + } + urlParams := macros.EndpointTemplateParams{SupplyId: config.ExtraAdapterInfo} - bidderEndpoint, err := macros.ResolveMacros(template, urlParams) + defaultEndpoint, err := macros.ResolveMacros(template, urlParams) if err != nil { return nil, fmt.Errorf("unable to resolve endpoint macros: %v", err) } return &adapter{ - bidderEndpoint: bidderEndpoint, + bidderEndpointTemplate: config.Endpoint, + defaultEndpoint: defaultEndpoint, + templateEndpoint: template, }, nil } diff --git a/adapters/thetradedesk/thetradedesk_test.go b/adapters/thetradedesk/thetradedesk_test.go index 658d812bcac..42166c4b76c 100644 --- a/adapters/thetradedesk/thetradedesk_test.go +++ b/adapters/thetradedesk/thetradedesk_test.go @@ -2,12 +2,13 @@ package thetradedesk import ( "encoding/json" + "github.com/prebid/prebid-server/v3/adapters/adapterstest" "net/http" "testing" + "text/template" "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/adapters" - "github.com/prebid/prebid-server/v3/adapters/adapterstest" "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/stretchr/testify/assert" @@ -116,15 +117,16 @@ func TestGetBidType(t *testing.T) { } } -func TestGetPublisherId(t *testing.T) { +func TestGetExtensionInfo(t *testing.T) { type args struct { impressions []openrtb2.Imp } tests := []struct { - name string - args args - expectedPublisherId string - wantErr bool + name string + args args + expectedPublisherId string + expectedSupplySourceId string + wantErr bool }{ { name: "valid_publisher_Id", @@ -132,12 +134,13 @@ func TestGetPublisherId(t *testing.T) { impressions: []openrtb2.Imp{ { Video: &openrtb2.Video{}, - Ext: json.RawMessage(`{"bidder":{"publisherId":"1"}}`), + Ext: json.RawMessage(`{"bidder":{"publisherId":"1", "supplySourceId": "abc"}}`), }, }, }, - expectedPublisherId: "1", - wantErr: false, + expectedPublisherId: "1", + expectedSupplySourceId: "abc", + wantErr: false, }, { name: "multiple_valid_publisher_Id", @@ -145,16 +148,17 @@ func TestGetPublisherId(t *testing.T) { impressions: []openrtb2.Imp{ { Video: &openrtb2.Video{}, - Ext: json.RawMessage(`{"bidder":{"publisherId":"1"}}`), + Ext: json.RawMessage(`{"bidder":{"publisherId":"1", "supplySourceId": "abc"}}`), }, { Video: &openrtb2.Video{}, - Ext: json.RawMessage(`{"bidder":{"publisherId":"2"}}`), + Ext: json.RawMessage(`{"bidder":{"publisherId":"2", "supplySourceId": "def"}}`), }, }, }, - expectedPublisherId: "1", - wantErr: false, + expectedPublisherId: "1", + expectedSupplySourceId: "abc", + wantErr: false, }, { name: "not_publisherId_present", @@ -166,8 +170,9 @@ func TestGetPublisherId(t *testing.T) { }, }, }, - expectedPublisherId: "", - wantErr: false, + expectedPublisherId: "", + expectedSupplySourceId: "", + wantErr: false, }, { name: "nil_publisherId_present", @@ -179,16 +184,18 @@ func TestGetPublisherId(t *testing.T) { }, }, }, - expectedPublisherId: "", - wantErr: false, + expectedPublisherId: "", + expectedSupplySourceId: "", + wantErr: false, }, { name: "no_impressions", args: args{ impressions: []openrtb2.Imp{}, }, - expectedPublisherId: "", - wantErr: false, + expectedPublisherId: "", + expectedSupplySourceId: "", + wantErr: false, }, { name: "invalid_bidder_object", @@ -200,15 +207,17 @@ func TestGetPublisherId(t *testing.T) { }, }, }, - expectedPublisherId: "", - wantErr: false, + expectedPublisherId: "", + expectedSupplySourceId: "", + wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - publisherId, err := getPublisherId(tt.args.impressions) + publisherId, supplySourceId, err := getExtensionInfo(tt.args.impressions) assert.Equal(t, tt.wantErr, err != nil) assert.Equal(t, tt.expectedPublisherId, publisherId) + assert.Equal(t, tt.expectedSupplySourceId, supplySourceId) }) } } @@ -268,9 +277,12 @@ func TestTheTradeDeskAdapter_MakeRequests(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - a := &adapter{ - bidderEndpoint: tt.fields.URI, - } + a, buildErr := Builder(openrtb_ext.BidderTheTradeDesk, config.Adapter{ + Endpoint: `https://adsrvr.org/bid/bidder/{{.SupplyId}}`, + ExtraAdapterInfo: "test", + }, config.Server{}) + assert.Nil(t, buildErr) + gotReqData, gotErr := a.MakeRequests(tt.args.request, tt.args.reqInfo) assert.Equal(t, tt.wantErr, len(gotErr) != 0) if tt.wantErr == false { @@ -374,12 +386,64 @@ func TestTheTradeDeskAdapter_MakeBids(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - a := &adapter{ - bidderEndpoint: tt.fields.URI, - } + a, buildErr := Builder(openrtb_ext.BidderTheTradeDesk, config.Adapter{ + Endpoint: `https://adsrvr.org/bid/bidder/{{.SupplyId}}`, + ExtraAdapterInfo: "test", + }, config.Server{}) + assert.Nil(t, buildErr) gotResp, gotErr := a.MakeBids(tt.args.internalRequest, tt.args.externalRequest, tt.args.response) assert.Equal(t, tt.wantErr, gotErr, gotErr) assert.Equal(t, tt.wantResp, gotResp) }) } } + +func TestTheTradeDeskAdapter_BuildEndpoint(t *testing.T) { + tests := []struct { + name string + supplySourceId string + defaultEndpoint string + expectedEndpoint string + wantErr []error + }{ + { + name: "valid_supply_source_id", + supplySourceId: "pub_abc", + defaultEndpoint: "https://direct.adsrvr.org/bid/bidder/default_publisher", + expectedEndpoint: "https://direct.adsrvr.org/bid/bidder/pub_abc", + wantErr: nil, + }, + { + name: "empty_supply_source_id", + supplySourceId: "", + defaultEndpoint: "https://direct.adsrvr.org/bid/bidder/default_publisher", + expectedEndpoint: "https://direct.adsrvr.org/bid/bidder/default_publisher", + wantErr: nil, + }, + { + name: "empty_ssi_and_no_default_expect_err", + supplySourceId: "", + defaultEndpoint: "", + expectedEndpoint: "", + wantErr: nil, + }, + } + + endpointTemplate, err := template.New("endpointTemplate").Parse("https://direct.adsrvr.org/bid/bidder/{{.SupplyId}}") + assert.Nil(t, err) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := &adapter{ + bidderEndpointTemplate: "https://direct.adsrvr.org/bid/bidder/{{.SupplyId}}", + defaultEndpoint: tt.defaultEndpoint, + templateEndpoint: endpointTemplate, + } + finalEndpoint, err := a.buildEndpointURL(tt.supplySourceId) + if tt.wantErr != nil { + assert.NotNil(t, err) + } + assert.Equal(t, tt.expectedEndpoint, finalEndpoint) + }) + } +} diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/ortb_response_video_parsing.json b/adapters/thetradedesk/thetradedesktest/exemplary/ortb_response_video_parsing.json new file mode 100644 index 00000000000..d0683a2d051 --- /dev/null +++ b/adapters/thetradedesk/thetradedesktest/exemplary/ortb_response_video_parsing.json @@ -0,0 +1,285 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "imp": [ + { + "instl": 0, + "ext": { + "gpid": "/1030006,22910642311/bakewithzoha/recipe", + "bidder": { + "publisherId": "123456" + } + }, + "id": "test-imp-id", + "bidfloorcur": "USD", + "bidfloor": 1.72, + "tagid": "pbs-local/preroll", + "video": { + "minduration": 5, + "startdelay": 0, + "api": [1, 2], + "w": 300, + "h": 169, + "mimes": [ + "application/javascript", + "video/mp4", + "video/webm" + ], + "protocols": [2, 3, 5, 6, 7, 8], + "maxduration": 30, + "placement": 3, + "plcmt": 4, + "skip": 1, + "content": { + "channel": { + "name": "Bake", + "domain": "https://ttd-bake.com/chicken-lasagna/" + }, + "context": 5, + "genre": "Food & Drink", + "cattax": 1, + "cat": ["IAB8", "IAB8", "IAB8-8"] + }, + "playbackmethod": [2] + } + } + ], + "cur": ["USD"], + "site": { + "publisher": { + "id": "123456" + }, + "mobile": 1, + "privacypolicy": 1, + "page": "https://example.com/chicken-lasagna/", + "domain": "ttd-bake.com", + "ref": "https://example.com/?s=easy+lasagna", + "id": "20619", + "name": "Bake With Zoha" + }, + "device": { + "js": 1, + "w": 1680, + "h": 1050, + "osv": "NT 10.0", + "os": "Windows", + "dnt": 0, + "language": "en", + "ip": "66.129.221.46", + "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36", + "sua": { + "source": 1, + "platform": { + "brand": "Windows" + }, + "browsers": [ + { + "brand": "Google Chrome", + "version": ["135"] + } + ], + "mobile": 0 + }, + "devicetype": 2 + }, + "test": 0, + "source": { + "fd": 1, + "pchain": "1363c924529b3998:20619", + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "example.com", + "sid": "050fd4e480110f1b92d451b879e6c780", + "hp": 1, + "rid": "4555b7da05efd4d4" + } + ] + } + } + }, + "bcat": ["211", "211", "181", "524", "271", "514"], + "cattax": 6, + "tmax": 750 + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://direct.adsrvr.org/bid/bidder/ttd", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id", + "imp": [ + { + "id": "test-imp-id", + "tagid": "pbs-local/preroll", + "bidfloorcur": "USD", + "bidfloor": 1.72, + "video": { + "minduration": 5, + "maxduration": 30, + "api": [1,2], + "mimes": [ + "application/javascript", + "video/mp4", + "video/webm" + ], + "placement": 3, + "protocols": [2, 3, 5, 6, 7, 8 ], + "w": 300, + "h": 169, + "playbackmethod": [2], + "plcmt": 4, + "skip": 1, + "startdelay": 0 + }, + "ext": { + "gpid": "/1030006,22910642311/bakewithzoha/recipe", + "bidder": { + "publisherId": "123456" + } + } + } + ], + "cur": ["USD"], + "site": { + "publisher": { + "id": "123456" + }, + "mobile": 1, + "privacypolicy": 1, + "page": "https://example.com/chicken-lasagna/", + "domain": "ttd-bake.com", + "ref": "https://example.com/?s=easy+lasagna", + "id": "20619", + "name": "Bake With Zoha" + }, + "device": { + "js": 1, + "w": 1680, + "h": 1050, + "osv": "NT 10.0", + "os": "Windows", + "dnt": 0, + "language": "en", + "ip": "66.129.221.46", + "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36", + "sua": { + "source": 1, + "platform": { + "brand": "Windows" + }, + "browsers": [ + { + "brand": "Google Chrome", + "version": ["135"] + } + ], + "mobile": 0 + }, + "devicetype": 2 + }, + "source": { + "fd": 1, + "pchain": "1363c924529b3998:20619", + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "example.com", + "sid": "050fd4e480110f1b92d451b879e6c780", + "hp": 1, + "rid": "4555b7da05efd4d4" + } + ] + } + } + }, + "bcat": ["211", "211", "181", "524", "271", "514"], + "cattax": 6, + "tmax": 750 + }, + "impIDs":["test-imp-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "test-imp-id", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "adm": "some-test-valid-adm", + "cid": "test-imp-id-ortb-cid", + "crid": "creative-123", + "adomain": [ + "ttd-ortb.com" + ], + "w": 640, + "h": 360, + "cat": [ + "286", + "287", + "313" + ], + "cattax": 6, + "mtype": 2, + "dur": 30 + } + ], + "seat": "5038" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "cid": "test-imp-id-ortb-cid", + "adm": "some-test-valid-adm", + "w": 640, + "h": 360, + "dur": 30, + "mtype": 2, + "adomain": [ + "ttd-ortb.com" + ], + "cattax": 6, + "cat": [ + "286", + "287", + "313" + ] + }, + "type": "video" + } + ] + } + ] +} + diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/prebidjs_response_video_parsing.json b/adapters/thetradedesk/thetradedesktest/exemplary/prebidjs_response_video_parsing.json new file mode 100644 index 00000000000..24a532d4368 --- /dev/null +++ b/adapters/thetradedesk/thetradedesktest/exemplary/prebidjs_response_video_parsing.json @@ -0,0 +1,308 @@ +{ + "mockBidRequest": { + "id": "3621b7f6603b81ea08", + "imp": [ + { + "id": "362240e73c1361aba", + "tagid": "/18190176,23070927648/AdThrive_Video_Coll_SOff_Smartphone/599de1450b08e2314df63095", + "video": { + "minduration": 1, + "maxduration": 15, + "api": [2, 7], + "mimes": ["video/mp4", "application/javascript"], + "placement": 1, + "protocols": [1, 2, 3, 4, 5, 6, 7, 8], + "w": 400, + "h": 225, + "playbackmethod": [6], + "plcmt": 2, + "pos": 1, + "startdelay": 0, + "linearity": 1, + "skip": 0, + "playbackend": 3 + }, + "bidfloor": 3.3507, + "bidfloorcur": "USD", + "secure": 1, + "ext": { + "bidder": { + "publisherId": "123456", + "supplySourceId": "pub_abc" + }, + "data": { + "adserver": { + "name": "gam", + "adslot": "/18190176,23070927648/AdThrive_Video_Coll_SOff_Smartphone/599de1450b08e2314df63095" + }, + "jwTargeting": { + "playerID": "s2WHEhYP", + "mediaID": "jJjdbKQW" + }, + "pbadslot": "/18190176,23070927648/AdThrive_Video_Coll_SOff_Smartphone/599de1450b08e2314df63095" + }, + "siteId": "1170765", + "gpid": "/18190176,23070927648/AdThrive_Video_Coll_SOff_Smartphone/599de1450b08e2314df63095" + } + } + ], + "site": { + "page": "ttd.com", + "id": "site-id" + }, + "device": { + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3.1 Mobile/15E148 Safari/604.1", + "dnt": 0, + "language": "en", + "connectiontype": 0, + "w": 375, + "h": 812, + "ext": { + "vpw": 375, + "vph": 740 + }, + "js": 1 + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "198lR19LYzIxODFxc1d5WGxCelQ5ZDh1NWhqNUI2NGU2UDdOYnpJdHpNSk0lMkZ3aDhJeEdmWEVhSSUyQkRUYzlJcSUyQjElMkJzWTkyeGNaRHBzd0xxNVN0WGR1UXd3blRFYzBLRG9mMlclMkJhbDY0VWhNNDdORlIyUnVPVGN5a2NqdlZwZlR4NzdYcGo", + "atype": 1 + } + ] + } + ] + } + }, + "at": 1, + "cur": ["USD"], + "source": { + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "example.com", + "sid": "599de1450b08e2314df63095", + "hp": 1 + } + ] + } + } + }, + "ext": { + "ttdprebid": { + "ver": "TTD-PREBID-2024.07.27", + "pbjs": "9.32.0", + "keywords": [] + } + }, + "bcat": [ + "IAB8-5", + "IAB8-18" + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://direct.adsrvr.org/bid/bidder/pub_abc", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ] + }, + "body": { + "id": "3621b7f6603b81ea08", + "at": 1, + "cur": ["USD"], + "bcat": [ + "IAB8-5", + "IAB8-18" + ], + "site": { + "id": "site-id", + "page": "ttd.com", + "publisher": { + "id": "123456" + } + }, + "source": { + "ext": { + "schain": { + "ver": "1.0", + "complete": 1, + "nodes": [ + { + "asi": "example.com", + "sid": "599de1450b08e2314df63095", + "hp": 1 + } + ] + } + } + }, + "user": { + "ext": { + "eids": [ + { + "source": "criteo.com", + "uids": [ + { + "id": "198lR19LYzIxODFxc1d5WGxCelQ5ZDh1NWhqNUI2NGU2UDdOYnpJdHpNSk0lMkZ3aDhJeEdmWEVhSSUyQkRUYzlJcSUyQjElMkJzWTkyeGNaRHBzd0xxNVN0WGR1UXd3blRFYzBLRG9mMlclMkJhbDY0VWhNNDdORlIyUnVPVGN5a2NqdlZwZlR4NzdYcGo", + "atype": 1 + } + ] + } + ] + } + }, + "ext": { + "ttdprebid": { + "ver": "TTD-PREBID-2024.07.27", + "pbjs": "9.32.0", + "keywords": [] + } + }, + "device": { + "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3.1 Mobile/15E148 Safari/604.1", + "dnt": 0, + "language": "en", + "connectiontype": 0, + "w": 375, + "h": 812, + "ext": { + "vpw": 375, + "vph": 740 + }, + "js": 1 + }, + "imp": [ + { + "id": "362240e73c1361aba", + "tagid": "/18190176,23070927648/AdThrive_Video_Coll_SOff_Smartphone/599de1450b08e2314df63095", + "video": { + "minduration": 1, + "maxduration": 15, + "api": [2, 7], + "mimes": ["video/mp4", "application/javascript"], + "placement": 1, + "protocols": [1, 2, 3, 4, 5, 6, 7, 8], + "w": 400, + "h": 225, + "playbackmethod": [6], + "plcmt": 2, + "pos": 1, + "startdelay": 0, + "linearity": 1, + "skip": 0, + "playbackend": 3 + }, + "bidfloor": 3.3507, + "bidfloorcur": "USD", + "secure": 1, + "ext": { + "bidder": { + "publisherId": "123456", + "supplySourceId": "pub_abc" + }, + "data": { + "adserver": { + "name": "gam", + "adslot": "/18190176,23070927648/AdThrive_Video_Coll_SOff_Smartphone/599de1450b08e2314df63095" + }, + "jwTargeting": { + "playerID": "s2WHEhYP", + "mediaID": "jJjdbKQW" + }, + "pbadslot": "/18190176,23070927648/AdThrive_Video_Coll_SOff_Smartphone/599de1450b08e2314df63095" + }, + "siteId": "1170765", + "gpid": "/18190176,23070927648/AdThrive_Video_Coll_SOff_Smartphone/599de1450b08e2314df63095" + } + } + ] + }, + "impIDs":["362240e73c1361aba"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "4555b7da05efd4d4", + "seatbid": [ + { + "bid": [ + { + "id": "ttd-bid-1", + "impid": "ttd-bid-1-impid", + "price": 0.1, + "adm": "some-test-ad-vast", + "cid": "ttd_cid", + "crid": "creative-123", + "adomain": [ + "ttd-bid.com" + ], + "w": 480, + "h": 360, + "cat": [ + "IAB22" + ], + "mtype": 2, + "ext": { + "advid": "u143h4c", + "duration": 15, + "viewabilityvendors": [], + "mediatype": 2 + } + } + ], + "seat": "1550" + } + ], + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "ttd-bid-1", + "impid": "ttd-bid-1-impid", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "w": 480, + "h": 360, + "adomain": [ + "ttd-bid.com" + ], + "cat": [ + "IAB22" + ], + "cid": "ttd_cid", + "mtype": 2, + "ext": { + "advid": "u143h4c", + "duration": 15, + "viewabilityvendors": [], + "mediatype": 2 + } + }, + "type": "video" + } + ] + } + ] +} + diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-inapp.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-inapp.json index e10445382c8..0b1ffe87001 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-inapp.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-inapp.json @@ -44,8 +44,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-multiple-bids-and-formats.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-multiple-bids-and-formats.json index 0180d48dde2..6219c7d5ed4 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-multiple-bids-and-formats.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-multiple-bids-and-formats.json @@ -70,8 +70,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id-multiple-bids", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-multiple-bids.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-multiple-bids.json index 4d46fa6907b..d9ab70a1d65 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-multiple-bids.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner-multiple-bids.json @@ -62,8 +62,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id-multiple-bids", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner.json index 4ac6acb0556..c7f904e524c 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-banner.json @@ -44,8 +44,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-empty-publisherId.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-empty-publisherId.json index ef6f6695553..f4ff473838d 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-empty-publisherId.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-empty-publisherId.json @@ -44,8 +44,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-multi-type-banner.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-multi-type-banner.json index 10286c96081..a09ed5c2f4e 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-multi-type-banner.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-multi-type-banner.json @@ -47,8 +47,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-multi-type-video.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-multi-type-video.json index e8f4bbca57c..01b39a4b7aa 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-multi-type-video.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-multi-type-video.json @@ -47,8 +47,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-native.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-native.json index 4d1b77ab0fb..8304adb1614 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-native.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-native.json @@ -29,8 +29,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/simple-video.json b/adapters/thetradedesk/thetradedesktest/exemplary/simple-video.json index 5dc945bab1f..e238b34faf5 100644 --- a/adapters/thetradedesk/thetradedesktest/exemplary/simple-video.json +++ b/adapters/thetradedesk/thetradedesktest/exemplary/simple-video.json @@ -49,8 +49,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/exemplary/use-supply-source-id-param.json b/adapters/thetradedesk/thetradedesktest/exemplary/use-supply-source-id-param.json new file mode 100644 index 00000000000..d7d330de57a --- /dev/null +++ b/adapters/thetradedesk/thetradedesktest/exemplary/use-supply-source-id-param.json @@ -0,0 +1,208 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "ttd.com" + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "pbs-local/preroll", + "video": { + "minduration": 0, + "maxduration": 60, + "api": [1,2], + "mimes": [ + "video/mp4", + "video/webm", + "application/javascript" + ], + "placement": 1, + "protocols": [2,3,4,5,6], + "w": 300, + "h": 250, + "playbackmethod": [1,2,3,4,5,6], + "plcmt": 1, + "skip": 1 + }, + "ext": { + "bidder": { + "publisherId": "123456", + "supplySourceId": "publisher_xyz" + } + } + }, + { + "id": "test-imp-id-2", + "tagid": "pbs-local/preroll", + "video": { + "minduration": 0, + "maxduration": 60, + "api": [1,2], + "mimes": [ + "video/mp4", + "video/webm", + "application/javascript" + ], + "placement": 1, + "protocols": [2,3,4,5,6], + "w": 300, + "h": 250, + "playbackmethod": [1,2,3,4,5,6], + "plcmt": 1, + "skip": 1 + }, + "ext": { + "bidder": { + "publisherId": "987654", + "supplySourceId": "publisher_abc" + } + } + } + ] + }, + "httpCalls": [ + { + "expectedRequest": { + "uri": "https://direct.adsrvr.org/bid/bidder/publisher_xyz", + "headers": { + "Content-Type": [ + "application/json;charset=utf-8" + ], + "Accept": [ + "application/json" + ] + }, + "body": { + "id": "test-request-id", + "site": { + "id": "site-id", + "page": "ttd.com", + "publisher": { + "id": "123456" + } + }, + "device": { + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "imp": [ + { + "id": "test-imp-id", + "tagid": "pbs-local/preroll", + "video": { + "maxduration": 60, + "api": [1,2], + "mimes": [ + "video/mp4", + "video/webm", + "application/javascript" + ], + "placement": 1, + "protocols": [2,3,4,5,6], + "w": 300, + "h": 250, + "playbackmethod": [1,2,3,4,5,6], + "plcmt": 1, + "skip": 1 + }, + "ext": { + "bidder": { + "publisherId": "123456", + "supplySourceId": "publisher_xyz" + } + } + }, + { + "id": "test-imp-id-2", + "tagid": "pbs-local/preroll", + "video": { + "maxduration": 60, + "api": [1,2], + "mimes": [ + "video/mp4", + "video/webm", + "application/javascript" + ], + "placement": 1, + "protocols": [2,3,4,5,6], + "w": 300, + "h": 250, + "playbackmethod": [1,2,3,4,5,6], + "plcmt": 1, + "skip": 1 + }, + "ext": { + "bidder": { + "publisherId": "987654", + "supplySourceId": "publisher_abc" + } + } + } + ] + }, + "impIDs":["test-imp-id", "test-imp-id-2"] + }, + "mockResponse": { + "status": 200, + "body": { + "currency": "USD", + "seatbid": [ + { + "bid": [ + { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "h": 250, + "w": 300, + "ext": { + "prebid": { + "type": "video" + } + }, + "mtype": 2 + } + ] + } + ] + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "test-slot-id", + "impid": "test-imp-id", + "price": 0.1, + "crid": "creative-123", + "adm": "some-test-ad-vast", + "h": 250, + "w": 300, + "ext": { + "prebid": { + "type": "video" + } + }, + "mtype": 2 + }, + "type": "video" + } + ] + } + ] +} + diff --git a/adapters/thetradedesk/thetradedesktest/supplemental/200-response-from-target.json b/adapters/thetradedesk/thetradedesktest/supplemental/200-response-from-target.json index fdbe15ac48e..fa92fd45e49 100644 --- a/adapters/thetradedesk/thetradedesktest/supplemental/200-response-from-target.json +++ b/adapters/thetradedesk/thetradedesktest/supplemental/200-response-from-target.json @@ -46,8 +46,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/supplemental/204-response-from-target.json b/adapters/thetradedesk/thetradedesktest/supplemental/204-response-from-target.json index a329982ea50..06407e7cb83 100644 --- a/adapters/thetradedesk/thetradedesktest/supplemental/204-response-from-target.json +++ b/adapters/thetradedesk/thetradedesktest/supplemental/204-response-from-target.json @@ -46,8 +46,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/supplemental/400-response-from-target.json b/adapters/thetradedesk/thetradedesktest/supplemental/400-response-from-target.json index ad5ffc62b51..a177c5835fe 100644 --- a/adapters/thetradedesk/thetradedesktest/supplemental/400-response-from-target.json +++ b/adapters/thetradedesk/thetradedesktest/supplemental/400-response-from-target.json @@ -46,8 +46,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/supplemental/500-response-from-target.json b/adapters/thetradedesk/thetradedesktest/supplemental/500-response-from-target.json index f2ccb342113..b6526b6fd20 100644 --- a/adapters/thetradedesk/thetradedesktest/supplemental/500-response-from-target.json +++ b/adapters/thetradedesk/thetradedesktest/supplemental/500-response-from-target.json @@ -46,8 +46,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/supplemental/invalid-mtype.json b/adapters/thetradedesk/thetradedesktest/supplemental/invalid-mtype.json index 52b392eb835..077587438b2 100644 --- a/adapters/thetradedesk/thetradedesktest/supplemental/invalid-mtype.json +++ b/adapters/thetradedesk/thetradedesktest/supplemental/invalid-mtype.json @@ -25,8 +25,7 @@ ], "Accept": [ "application/json" - ], - "X-Integration-Type": ["1"] + ] }, "body": { "id": "test-request-id", diff --git a/adapters/thetradedesk/thetradedesktest/supplemental/invalid-supplySourceId.json b/adapters/thetradedesk/thetradedesktest/supplemental/invalid-supplySourceId.json new file mode 100644 index 00000000000..69f7898ccff --- /dev/null +++ b/adapters/thetradedesk/thetradedesktest/supplemental/invalid-supplySourceId.json @@ -0,0 +1,45 @@ +{ + "mockBidRequest": { + "id": "test-request-id", + "app": { + "bundle": "test.app.bundle", + "publisher": { + "id": "this_id_will_be_replaced" + } + }, + "device": { + "ifa": "test-ifa-123456", + "os": "android", + "ip": "91.199.242.236", + "ua": "random user agent" + }, + "imp": [ + { + "id": "test-imp-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + } + ], + "w": 300, + "h": 250 + }, + "ext": { + "bidder": { + "supplySourceId": 55555 + } + } + } + ] + }, + "httpCalls": [], + "expectedMakeRequestsErrors": [ + { + "value": "cannot unmarshal openrtb_ext.ExtImpTheTradeDesk.SupplySourceId: expects \" or n, but found 5", + "comparison": "literal" + } + ] +} + diff --git a/adapters/zeta_global_ssp/params_test.go b/adapters/zeta_global_ssp/params_test.go new file mode 100644 index 00000000000..d665d3da0f7 --- /dev/null +++ b/adapters/zeta_global_ssp/params_test.go @@ -0,0 +1,53 @@ +package zeta_global_ssp_test + +import ( + "encoding/json" + "testing" + + "github.com/prebid/prebid-server/v3/openrtb_ext" +) + +func TestValidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, validParam := range validParams { + if err := validator.Validate(openrtb_ext.BidderZetaGlobalSsp, json.RawMessage(validParam)); err != nil { + t.Errorf("Schema rejected valid params: %s", validParam) + } + } +} + +func TestInvalidParams(t *testing.T) { + validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params") + if err != nil { + t.Fatalf("Failed to fetch the json-schemas. %v", err) + } + + for _, invalidParam := range invalidParams { + if err := validator.Validate(openrtb_ext.BidderZetaGlobalSsp, json.RawMessage(invalidParam)); err == nil { + t.Errorf("Schema allowed unexpected params: %s", invalidParam) + } + } +} + +var validParams = []string{ + `{"sid": 123}`, + `{}`, +} + +var invalidParams = []string{ + ``, + `null`, + `true`, + `5`, + `4.2`, + `[]`, + `some_string`, + `{"sid": ""}`, + `{"sid": "some_string"}`, + `{"sid": "4.2"}`, + `{"sid": "123"}`, +} diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/audio.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/audio.json new file mode 100644 index 00000000000..c1f1653f169 --- /dev/null +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/audio.json @@ -0,0 +1,140 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "site": { + "page": "http://www.example.com", + "domain": "www.example.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "imp": [ + { + "id": "some-impression-id", + "audio": { + "minduration": 5, + "maxduration": 30, + "minbitrate": 300, + "maxbitrate": 1500, + "api": [1, 2], + "protocols": [9, 10], + "mimes": [ + "audio/aac", + "audio/mp4", + "audio/mpeg" + ] + }, + "ext": { + "bidder": { + "sid": 11 + } + } + } + ], + "test": 1, + "tmax": 500 + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ] + }, + "uri": "https://ssp.disqus.com/bid/prebid-server?sid=11", + "body": { + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id", + "audio": { + "minduration": 5, + "maxduration": 30, + "minbitrate": 300, + "maxbitrate": 1500, + "api": [1, 2], + "protocols": [9, 10], + "mimes": [ + "audio/aac", + "audio/mp4", + "audio/mpeg" + ] + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "test": 1, + "tmax": 500 + }, + "impIDs":["some-impression-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "some-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "1", + "impid": "some-impression-id", + "price": 1.234, + "adm": "TAG", + "adomain": [ + "some-adomain" + ], + "cid": "1234", + "crid": "2345", + "ext": { + "prebid": { + "type": "audio" + } + } + } + ], + "seat": "zeta_global_ssp" + } + ], + "bidid": "some-bidid", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "1", + "impid": "some-impression-id", + "price": 1.234, + "adm": "TAG", + "adomain": [ + "some-adomain" + ], + "cid": "1234", + "crid": "2345", + "ext": { + "prebid": { + "type": "audio" + } + } + }, + "type": "audio" + } + ] + } + ] +} diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/banner.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/banner.json index 3b0918e6858..620c4d2c2e9 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/banner.json +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/banner.json @@ -26,7 +26,9 @@ ] }, "ext": { - "bidder": {} + "bidder": { + "sid": 11 + } } } ], @@ -63,9 +65,6 @@ ], "w": 300, "h": 250 - }, - "ext": { - "bidder": {} } } ], diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/no-bid.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/no-bid.json index ebb85839138..535cd524240 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/no-bid.json +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/no-bid.json @@ -26,7 +26,9 @@ ] }, "ext": { - "bidder": {} + "bidder": { + "sid": 11 + } } } ], @@ -63,9 +65,6 @@ ], "w": 300, "h": 250 - }, - "ext": { - "bidder": {} } } ], diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/video.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/video.json index 2677ea5f1ca..1a6f5e571d7 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/video.json +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/exemplary/video.json @@ -6,7 +6,9 @@ { "id": "some-impression-id", "ext": { - "bidder": {} + "bidder": { + "sid": 11 + } }, "video": { "w": 640, @@ -49,9 +51,6 @@ "imp": [ { "id": "some-impression-id", - "ext": { - "bidder": {} - }, "video": { "w": 640, "h": 480, diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/bad-request.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/bad-request.json index 88215a085a3..bd3654b1c68 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/bad-request.json +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/bad-request.json @@ -26,7 +26,9 @@ ] }, "ext": { - "bidder": {} + "bidder": { + "sid": 11 + } } } ], @@ -63,9 +65,6 @@ ], "w": 300, "h": 250 - }, - "ext": { - "bidder": {} } } ], diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-bid-type.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-bid-type.json index 5ed9230e949..5f1e4047798 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-bid-type.json +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-bid-type.json @@ -26,7 +26,9 @@ ] }, "ext": { - "bidder": {} + "bidder": { + "sid": 11 + } } } ], @@ -63,9 +65,6 @@ ], "w": 300, "h": 250 - }, - "ext": { - "bidder": {} } } ], diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-imp-ext-bidder.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-imp-ext-bidder.json new file mode 100644 index 00000000000..86c7b99341f --- /dev/null +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-imp-ext-bidder.json @@ -0,0 +1,42 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "site": { + "page": "http://www.example.com", + "domain": "www.example.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "w": 300, + "h": 250, + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": "" + } + } + ], + "test": 1, + "tmax": 500 + }, + "expectedMakeRequestsErrors": [ + { + "value": "imp.ext.bidder not provided or cannot be unmarshalled", + "comparison": "literal" + } + ] +} diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-imp-ext.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-imp-ext.json new file mode 100644 index 00000000000..36dfb29599d --- /dev/null +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/invalid-imp-ext.json @@ -0,0 +1,40 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "site": { + "page": "http://www.example.com", + "domain": "www.example.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "w": 300, + "h": 250, + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": "" + } + ], + "test": 1, + "tmax": 500 + }, + "expectedMakeRequestsErrors": [ + { + "value": "imp.ext not provided or cannot be unmarshalled", + "comparison": "literal" + } + ] +} diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/no-bid-type.json.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/no-bid-type.json.json index f0065941df0..193923dbb61 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/no-bid-type.json.json +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/no-bid-type.json.json @@ -26,7 +26,9 @@ ] }, "ext": { - "bidder": {} + "bidder": { + "sid": 11 + } } } ], @@ -63,9 +65,6 @@ ], "w": 300, "h": 250 - }, - "ext": { - "bidder": {} } } ], diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/no-sid-param.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/no-sid-param.json new file mode 100644 index 00000000000..66f20396720 --- /dev/null +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/no-sid-param.json @@ -0,0 +1,144 @@ +{ + "mockBidRequest": { + "id": "some-request-id", + "site": { + "page": "http://www.example.com", + "domain": "www.example.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "w": 300, + "h": 250, + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": {} + } + } + ], + "test": 1, + "tmax": 500 + }, + "httpCalls": [ + { + "expectedRequest": { + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json;charset=utf-8" + ] + }, + "uri": "https://ssp.disqus.com/bid/prebid-server?sid=0", + "body": { + "id": "some-request-id", + "imp": [ + { + "id": "some-impression-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ], + "w": 300, + "h": 250 + } + } + ], + "site": { + "domain": "www.example.com", + "page": "http://www.example.com" + }, + "device": { + "ip": "123.123.123.123" + }, + "test": 1, + "tmax": 500 + }, + "impIDs":["some-impression-id"] + }, + "mockResponse": { + "status": 200, + "body": { + "id": "some-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "1", + "impid": "some-impression-id", + "price": 1.234, + "adm": "", + "adomain": [ + "some-adomain" + ], + "cid": "1234", + "crid": "2345", + "h": 1, + "w": 1, + "ext": { + "prebid": { + "type": "banner" + } + } + } + ], + "seat": "zeta_global_ssp" + } + ], + "bidid": "some-bidid", + "cur": "USD" + } + } + } + ], + "expectedBidResponses": [ + { + "currency": "USD", + "bids": [ + { + "bid": { + "id": "1", + "impid": "some-impression-id", + "price": 1.234, + "adm": "", + "adomain": [ + "some-adomain" + ], + "cid": "1234", + "crid": "2345", + "h": 1, + "w": 1, + "ext": { + "prebid": { + "type": "banner" + } + } + }, + "type": "banner" + } + ] + } + ] +} diff --git a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/server-error.json b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/server-error.json index 0ec1555ffb7..a06b3741cb0 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/server-error.json +++ b/adapters/zeta_global_ssp/zeta_global_ssp-test/supplemental/server-error.json @@ -26,7 +26,9 @@ ] }, "ext": { - "bidder": {} + "bidder": { + "sid": 11 + } } } ], @@ -63,9 +65,6 @@ ], "w": 300, "h": 250 - }, - "ext": { - "bidder": {} } } ], diff --git a/adapters/zeta_global_ssp/zeta_global_ssp.go b/adapters/zeta_global_ssp/zeta_global_ssp.go index e06c6f05eff..59a912c1629 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp.go +++ b/adapters/zeta_global_ssp/zeta_global_ssp.go @@ -4,28 +4,46 @@ import ( "encoding/json" "fmt" "net/http" + "strconv" + "text/template" "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/adapters" "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/errortypes" + "github.com/prebid/prebid-server/v3/macros" "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/prebid/prebid-server/v3/util/jsonutil" ) type adapter struct { - endpoint string + endpoint *template.Template } func Builder(bidderName openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) { + endpointTemplate, err := template.New("endpointTemplate").Parse(config.Endpoint) + if err != nil { + return nil, fmt.Errorf("unable to parse endpoint url template: %v", err) + } + bidder := &adapter{ - endpoint: config.Endpoint, + endpoint: endpointTemplate, } return bidder, nil } func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) { - requestJson, err := json.Marshal(request) + zetaSspImpExt, err := a.getImpressionExt(&request.Imp[0]) + if err != nil { + return nil, []error{err} + } + + endpointURL, err := a.buildEndpointURL(zetaSspImpExt) + if err != nil { + return nil, []error{err} + } + + requestJSON, err := json.Marshal(request) if err != nil { return nil, []error{err} } @@ -36,8 +54,8 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte requestData := &adapters.RequestData{ Method: "POST", - Uri: a.endpoint, - Body: requestJson, + Uri: endpointURL, + Body: requestJSON, Headers: headers, ImpIDs: openrtb_ext.GetImpIDs(request.Imp), } @@ -45,6 +63,28 @@ func (a *adapter) MakeRequests(request *openrtb2.BidRequest, requestInfo *adapte return []*adapters.RequestData{requestData}, nil } +func (a *adapter) getImpressionExt(imp *openrtb2.Imp) (*openrtb_ext.ImpExtZetaGlobalSsp, error) { + var bidderExt adapters.ExtImpBidder + if err := json.Unmarshal(imp.Ext, &bidderExt); err != nil { + return nil, &errortypes.BadInput{ + Message: "imp.ext not provided or cannot be unmarshalled", + } + } + var zetaSspImpExt openrtb_ext.ImpExtZetaGlobalSsp + if err := json.Unmarshal(bidderExt.Bidder, &zetaSspImpExt); err != nil { + return nil, &errortypes.BadInput{ + Message: "imp.ext.bidder not provided or cannot be unmarshalled", + } + } + imp.Ext = nil + return &zetaSspImpExt, nil +} + +func (a *adapter) buildEndpointURL(params *openrtb_ext.ImpExtZetaGlobalSsp) (string, error) { + endpointParams := macros.EndpointTemplateParams{AccountID: strconv.Itoa(params.Sid)} + return macros.ResolveMacros(a.endpoint, endpointParams) +} + func (a *adapter) MakeBids(request *openrtb2.BidRequest, requestData *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) { if adapters.IsResponseStatusCodeNoContent(responseData) { return nil, nil diff --git a/adapters/zeta_global_ssp/zeta_global_ssp_test.go b/adapters/zeta_global_ssp/zeta_global_ssp_test.go index f2b51409165..f7e9b36698d 100644 --- a/adapters/zeta_global_ssp/zeta_global_ssp_test.go +++ b/adapters/zeta_global_ssp/zeta_global_ssp_test.go @@ -6,11 +6,12 @@ import ( "github.com/prebid/prebid-server/v3/adapters/adapterstest" "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/openrtb_ext" + "github.com/stretchr/testify/assert" ) func TestJsonSamples(t *testing.T) { bidder, buildErr := Builder(openrtb_ext.BidderZetaGlobalSsp, config.Adapter{ - Endpoint: "https://ssp.disqus.com/bid/prebid-server?sid=11"}, + Endpoint: "https://ssp.disqus.com/bid/prebid-server?sid={{.AccountID}}"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) if buildErr != nil { @@ -19,3 +20,11 @@ func TestJsonSamples(t *testing.T) { adapterstest.RunJSONBidderTest(t, "zeta_global_ssp-test", bidder) } + +func TestEndpointTemplateMalformed(t *testing.T) { + _, buildErr := Builder(openrtb_ext.BidderZetaGlobalSsp, config.Adapter{ + Endpoint: "{{Malformed}}"}, + config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"}) + + assert.Error(t, buildErr) +} diff --git a/adservertargeting/respdataprocessor.go b/adservertargeting/respdataprocessor.go index c3ad25aa62a..529abcfd15a 100644 --- a/adservertargeting/respdataprocessor.go +++ b/adservertargeting/respdataprocessor.go @@ -8,7 +8,7 @@ import ( "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/openrtb_ext" "github.com/prebid/prebid-server/v3/util/jsonutil" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" ) const MaxKeyLength = 20 diff --git a/config/account.go b/config/account.go index 310fd021dce..3d7e0f8c804 100644 --- a/config/account.go +++ b/config/account.go @@ -42,6 +42,7 @@ type Account struct { DefaultBidLimit int `mapstructure:"default_bid_limit" json:"default_bid_limit"` BidAdjustments *openrtb_ext.ExtRequestPrebidBidAdjustments `mapstructure:"bidadjustments" json:"bidadjustments"` Privacy AccountPrivacy `mapstructure:"privacy" json:"privacy"` + PreferredMediaType openrtb_ext.PreferredMediaType `mapstructure:"preferredmediatype" json:"preferredmediatype"` } // CookieSync represents the account-level defaults for the cookie sync endpoint. diff --git a/config/bidderinfo.go b/config/bidderinfo.go index d553df1f4e5..87771b402e1 100644 --- a/config/bidderinfo.go +++ b/config/bidderinfo.go @@ -96,8 +96,9 @@ type AdapterXAPI struct { // Version is not yet actively supported // GPPSupported is not yet actively supported type OpenRTBInfo struct { - Version string `yaml:"version" mapstructure:"version"` - GPPSupported bool `yaml:"gpp-supported" mapstructure:"gpp-supported"` + Version string `yaml:"version" mapstructure:"version"` + GPPSupported bool `yaml:"gpp-supported" mapstructure:"gpp-supported"` + MultiformatSupported *bool `yaml:"multiformat-supported" mapstructure:"multiformat-supported"` } // Syncer specifies the user sync settings for a bidder. This struct is shared by the account config, diff --git a/config/bidderinfo_test.go b/config/bidderinfo_test.go index 9ad64ee213f..0b9547d0d67 100644 --- a/config/bidderinfo_test.go +++ b/config/bidderinfo_test.go @@ -47,6 +47,7 @@ endpointCompression: GZIP openrtb: version: 2.6 gpp-supported: true + multiformat-supported: false endpoint: https://endpoint.com disabled: false extra_info: extra-info @@ -122,12 +123,15 @@ func TestLoadBidderInfoFromDisk(t *testing.T) { } func TestProcessBidderInfo(t *testing.T) { + falseValue := false + testCases := []struct { description string bidderInfos map[string][]byte expectedBidderInfos BidderInfos expectError string }{ + { description: "Valid bidder info", bidderInfos: map[string][]byte{ @@ -205,8 +209,9 @@ func TestProcessBidderInfo(t *testing.T) { }, ModifyingVastXmlAllowed: true, OpenRTB: &OpenRTBInfo{ - GPPSupported: true, - Version: "2.6", + GPPSupported: true, + Version: "2.6", + MultiformatSupported: &falseValue, }, PlatformID: "123", Syncer: &Syncer{ @@ -256,8 +261,9 @@ func TestProcessBidderInfo(t *testing.T) { }, ModifyingVastXmlAllowed: true, OpenRTB: &OpenRTBInfo{ - GPPSupported: true, - Version: "2.6", + GPPSupported: true, + Version: "2.6", + MultiformatSupported: &falseValue, }, PlatformID: "123", Syncer: &Syncer{ @@ -285,6 +291,9 @@ func TestProcessBidderInfo(t *testing.T) { } func TestProcessAliasBidderInfo(t *testing.T) { + + trueValue := true + parentWithSyncerKey := BidderInfo{ AppSecret: "app-secret", Capabilities: &CapabilitiesInfo{ @@ -313,8 +322,9 @@ func TestProcessAliasBidderInfo(t *testing.T) { }, ModifyingVastXmlAllowed: true, OpenRTB: &OpenRTBInfo{ - GPPSupported: true, - Version: "2.6", + GPPSupported: true, + Version: "2.6", + MultiformatSupported: &trueValue, }, PlatformID: "123", Syncer: &Syncer{ @@ -360,8 +370,9 @@ func TestProcessAliasBidderInfo(t *testing.T) { }, ModifyingVastXmlAllowed: false, OpenRTB: &OpenRTBInfo{ - GPPSupported: false, - Version: "2.5", + GPPSupported: false, + Version: "2.5", + MultiformatSupported: &trueValue, }, PlatformID: "456", Syncer: &Syncer{ @@ -1887,7 +1898,7 @@ func TestApplyBidderInfoConfigOverridesInvalid(t *testing.T) { func TestReadFullYamlBidderConfig(t *testing.T) { bidder := "bidderA" bidderInf := BidderInfo{} - + falseValue := false err := yaml.Unmarshal([]byte(fullBidderYAMLConfig), &bidderInf) require.NoError(t, err) @@ -1934,8 +1945,9 @@ func TestReadFullYamlBidderConfig(t *testing.T) { }, EndpointCompression: "GZIP", OpenRTB: &OpenRTBInfo{ - GPPSupported: true, - Version: "2.6", + GPPSupported: true, + Version: "2.6", + MultiformatSupported: &falseValue, }, Disabled: false, ExtraAdapterInfo: "extra-info", diff --git a/currency/aggregate_conversions_test.go b/currency/aggregate_conversions_test.go index d2ac961a8a7..d31422737d6 100644 --- a/currency/aggregate_conversions_test.go +++ b/currency/aggregate_conversions_test.go @@ -64,9 +64,16 @@ func TestGroupedGetRate(t *testing.T) { }, }, { - expectedError: ConversionNotFoundError{FromCur: "GBP", ToCur: "EUR"}, + expectedError: ConversionNotFoundError{FromCur: "RON", ToCur: "EUR"}, testCases: []aTest{ - {"Valid three-digit currency codes, but conversion rate not found", "GBP", "EUR", 0}, + {"Valid three-digit currency codes, but conversion from-currency rate not found", "RON", "EUR", 0}, + {"Valid three-digit currency codes, but conversion to-currency rate not found", "EUR", "RON", 0}, + }, + }, + { + expectedError: nil, + testCases: []aTest{ + {"Valid three-digit currency codes, intermediate conversion rate has been used", "GBP", "EUR", 2 / 3.0}, }, }, } diff --git a/currency/rates.go b/currency/rates.go index f36eddfac81..87d40469627 100644 --- a/currency/rates.go +++ b/currency/rates.go @@ -20,6 +20,22 @@ func NewRates(conversions map[string]map[string]float64) *Rates { } } +// FindIntermediateConversionRate returns the conversion rate between two currencies +// if a valid conversion exists in the provided rates container. +// Otherwise, it returns a ConversionNotFoundError. +func FindIntermediateConversionRate(r *Rates, from, to currency.Unit) (float64, error) { + for _, conversions := range r.Conversions { + toRate, hasToRate := conversions[to.String()] + fromRate, hasFromRate := conversions[from.String()] + + if hasToRate && hasFromRate { + return toRate / fromRate, nil + } + } + + return 0, ConversionNotFoundError{FromCur: from.String(), ToCur: to.String()} +} + // GetRate returns the conversion rate between two currencies or: // - An error if one of the currency strings is not well-formed // - An error if any of the currency strings is not a recognized currency code. @@ -46,7 +62,9 @@ func (r *Rates) GetRate(from, to string) (float64, error) { // In case we have an entry TO -> FROM return 1 / conversion, nil } - return 0, ConversionNotFoundError{FromCur: fromUnit.String(), ToCur: toUnit.String()} + + // Try to find currency rates via intermediate currency + return FindIntermediateConversionRate(r, fromUnit, toUnit) } return 0, errors.New("rates are nil") } diff --git a/currency/rates_test.go b/currency/rates_test.go index 6fb444f32c4..555d299d212 100644 --- a/currency/rates_test.go +++ b/currency/rates_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/prebid/prebid-server/v3/util/jsonutil" + "golang.org/x/text/currency" ) func TestUnMarshallRates(t *testing.T) { @@ -186,6 +187,82 @@ func TestGetRate_ReverseConversion(t *testing.T) { } } +func TestGetRate_FindIntermediateConversionRate(t *testing.T) { + rates := NewRates(map[string]map[string]float64{ + "USD": { + "SEK": 10.23842, + "NOK": 10.47089, + }, + "EUR": { + "THB": 35.23842, + "ZAR": 18.47089, + }, + }) + + testCases := []struct { + description string + from string + to string + expectedRate float64 + hasError bool + }{ + { + description: "in_same_intermediate_USD_currency", + from: "NOK", + to: "SEK", + expectedRate: 0.9777984488424574, + }, + { + description: "in_same_intermediate_USD_currency_inverse", + from: "SEK", + to: "NOK", + expectedRate: 1 / 0.9777984488424574, + }, + { + description: "in_same_intermediate_EUR_currency", + from: "THB", + to: "ZAR", + expectedRate: 0.5241690745498806, + }, + { + description: "in_same_intermediate_EUR_currency_inverse", + from: "ZAR", + to: "THB", + expectedRate: 1 / 0.5241690745498806, + }, + { + description: "in_different_intermediate_currencies", + from: "NOK", + to: "ZAR", + expectedRate: 0, + hasError: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + fromUnit, err := currency.ParseISO(tc.from) + if err != nil { + t.Errorf("Expected no error, but got: %v", err) + } + toUnit, err := currency.ParseISO(tc.to) + if err != nil { + t.Errorf("Expected no error, but got: %v", err) + } + + rate, err := FindIntermediateConversionRate(rates, fromUnit, toUnit) + + if tc.hasError { + assert.NotNil(t, err) + assert.Equal(t, float64(0), rate) + } else { + assert.Nil(t, err) + assert.Equal(t, tc.expectedRate, rate) + } + }) + } +} + func TestGetRate_EmptyRates(t *testing.T) { // Setup: diff --git a/endpoints/openrtb2/amp_auction.go b/endpoints/openrtb2/amp_auction.go index b596ec793c6..6f37d49fca5 100644 --- a/endpoints/openrtb2/amp_auction.go +++ b/endpoints/openrtb2/amp_auction.go @@ -19,7 +19,7 @@ import ( "github.com/prebid/prebid-server/v3/hooks/hookexecution" "github.com/prebid/prebid-server/v3/ortb" "github.com/prebid/prebid-server/v3/util/uuidutil" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" accountService "github.com/prebid/prebid-server/v3/account" "github.com/prebid/prebid-server/v3/amp" diff --git a/endpoints/openrtb2/amp_auction_test.go b/endpoints/openrtb2/amp_auction_test.go index 3fe8a629f02..78a967facec 100644 --- a/endpoints/openrtb2/amp_auction_test.go +++ b/endpoints/openrtb2/amp_auction_test.go @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/prebid/prebid-server/v3/adapters" "github.com/prebid/prebid-server/v3/amp" "github.com/prebid/prebid-server/v3/analytics" analyticsBuild "github.com/prebid/prebid-server/v3/analytics/build" @@ -146,7 +147,7 @@ func TestGoodAmpRequests(t *testing.T) { t.Fatalf("Unexpected bidder %s has an expected mock bidder request. Test file: %s", bidder, filename) } aa := a.(*exchange.BidderAdapter) - ma := aa.Bidder.(*mockAdapter) + ma := aa.Bidder.(*adapters.InfoAwareBidder).Bidder.(*mockAdapter) assert.JSONEq(t, string(req), string(ma.requestData[0]), "Not the expected mock bidder request for bidder %s. Test file: %s", bidder, filename) } } diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index e4faa7e9cb8..84835f0bf12 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -29,7 +29,7 @@ import ( "github.com/prebid/prebid-server/v3/privacysandbox" "github.com/prebid/prebid-server/v3/schain" "golang.org/x/net/publicsuffix" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" accountService "github.com/prebid/prebid-server/v3/account" "github.com/prebid/prebid-server/v3/analytics" @@ -1277,23 +1277,64 @@ func (deps *endpointDeps) validateUser(req *openrtb_ext.RequestWrapper, aliases } // Check Universal User ID - for eidIndex, eid := range req.User.EIDs { + if len(req.User.EIDs) > 0 { + + validEids, eidErrors := validateEIDs(req.User.EIDs) + + if len(eidErrors) > 0 { + errL = append(errL, eidErrors...) + } + req.User.EIDs = validEids + } + + return errL +} + +func validateEIDs(eids []openrtb2.EID) ([]openrtb2.EID, []error) { + var errorsList []error + validEIDs := make([]openrtb2.EID, 0, len(eids)) + + for eidIndex, eid := range eids { if eid.Source == "" { - return append(errL, fmt.Errorf("request.user.eids[%d] missing required field: \"source\"", eidIndex)) + errorsList = append(errorsList, &errortypes.Warning{ + Message: fmt.Sprintf("request.user.eids[%d] removed due to missing source", eidIndex), + WarningCode: errortypes.InvalidUserEIDsWarningCode, + }) + continue } + validUIDs, uidErrors := validateUIDs(eid.UIDs, eidIndex) + errorsList = append(errorsList, uidErrors...) - if len(eid.UIDs) == 0 { - return append(errL, fmt.Errorf("request.user.eids[%d].uids must contain at least one element or be undefined", eidIndex)) + if len(validUIDs) > 0 { + eid.UIDs = validUIDs + validEIDs = append(validEIDs, eid) + } else { + errorsList = append(errorsList, &errortypes.Warning{ + Message: fmt.Sprintf("request.user.eids[%d] (source: %s) removed due to empty uids", eidIndex, eid.Source), + WarningCode: errortypes.InvalidUserEIDsWarningCode, + }) } + } - for uidIndex, uid := range eid.UIDs { - if uid.ID == "" { - return append(errL, fmt.Errorf("request.user.eids[%d].uids[%d] missing required field: \"id\"", eidIndex, uidIndex)) - } + return validEIDs, errorsList +} + +func validateUIDs(uids []openrtb2.UID, eidIndex int) ([]openrtb2.UID, []error) { + var validUIDs []openrtb2.UID + var uidErrors []error + + for uidIndex, uid := range uids { + if uid.ID != "" { + validUIDs = append(validUIDs, uid) + } else { + uidErrors = append(uidErrors, &errortypes.Warning{ + Message: fmt.Sprintf("request.user.eids[%d].uids[%d] removed due to empty ids", eidIndex, uidIndex), + WarningCode: errortypes.InvalidUserUIDsWarningCode, + }) } } - return errL + return validUIDs, uidErrors } func validateRegs(req *openrtb_ext.RequestWrapper, gpp gpplib.GppContainer) []error { diff --git a/endpoints/openrtb2/auction_benchmark_test.go b/endpoints/openrtb2/auction_benchmark_test.go index 9697687407e..5dfaecdda91 100644 --- a/endpoints/openrtb2/auction_benchmark_test.go +++ b/endpoints/openrtb2/auction_benchmark_test.go @@ -76,7 +76,7 @@ func BenchmarkOpenrtbEndpoint(b *testing.B) { nilMetrics := &metricsConfig.NilMetricsEngine{} - adapters, adaptersErr := exchange.BuildAdapters(server.Client(), &config.Configuration{}, infos, nilMetrics) + adapters, singleFormatBidders, adaptersErr := exchange.BuildAdapters(server.Client(), &config.Configuration{}, infos, nilMetrics) if adaptersErr != nil { b.Fatal("unable to build adapters") } @@ -99,6 +99,7 @@ func BenchmarkOpenrtbEndpoint(b *testing.B) { &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, + singleFormatBidders, ) endpoint, _ := NewEndpoint( diff --git a/endpoints/openrtb2/auction_test.go b/endpoints/openrtb2/auction_test.go index dfc4f441cfe..1fc6e50346d 100644 --- a/endpoints/openrtb2/auction_test.go +++ b/endpoints/openrtb2/auction_test.go @@ -21,7 +21,9 @@ import ( "github.com/buger/jsonparser" jsoniter "github.com/json-iterator/go" "github.com/julienschmidt/httprouter" + gpplib "github.com/prebid/go-gpp" "github.com/prebid/openrtb/v20/openrtb2" + "github.com/prebid/prebid-server/v3/adapters" "github.com/prebid/prebid-server/v3/analytics" analyticsBuild "github.com/prebid/prebid-server/v3/analytics/build" "github.com/prebid/prebid-server/v3/config" @@ -172,6 +174,7 @@ func runJsonBasedTest(t *testing.T, filename, desc string) { cfg.BlockedApps = test.Config.BlockedApps cfg.BlockedAppsLookup = test.Config.getBlockedAppLookup() cfg.AccountRequired = test.Config.AccountRequired + cfg.AccountDefaults.PreferredMediaType = test.Config.PreferredMediaType } cfg.MarshalAccountDefaults() test.endpointType = OPENRTB_ENDPOINT @@ -195,7 +198,7 @@ func runJsonBasedTest(t *testing.T, filename, desc string) { t.Fatalf("Unexpected bidder %s has an expected mock bidder request. Test file: %s", bidder, filename) } aa := a.(*exchange.BidderAdapter) - ma := aa.Bidder.(*mockAdapter) + ma := aa.Bidder.(*adapters.InfoAwareBidder).Bidder.(*mockAdapter) assert.JSONEq(t, string(req), string(ma.requestData[0]), "Not the expected mock bidder request for bidder %s. Test file: %s", bidder, filename) } } @@ -5998,3 +6001,381 @@ func sortUserData(user *openrtb2.User) { } } } +func TestValidateEIDs(t *testing.T) { + testCases := []struct { + name string + input []openrtb2.EID + expected []openrtb2.EID + numErrors int + expectedErrorMessages []string + }{ + { + name: "one-eid-one-uid-valid", + input: []openrtb2.EID{ + {Source: "src1", UIDs: []openrtb2.UID{{ID: "id1"}}}, + }, + expected: []openrtb2.EID{ + {Source: "src1", UIDs: []openrtb2.UID{{ID: "id1"}}}, + }, + numErrors: 0, + expectedErrorMessages: nil, + }, + { + name: "one-eid-one-uid-empty", + input: []openrtb2.EID{ + {Source: "src2", UIDs: []openrtb2.UID{{ID: ""}}}, + }, + expected: []openrtb2.EID{}, + numErrors: 2, + expectedErrorMessages: []string{ + "request.user.eids[0].uids[0] removed due to empty ids", + "request.user.eids[0] (source: src2) removed due to empty uids", + }, + }, + { + name: "many-mixed", + input: []openrtb2.EID{ + {Source: "src3", UIDs: []openrtb2.UID{{ID: "ID1"}, {ID: "ID2"}}}, + {Source: "src4", UIDs: []openrtb2.UID{{ID: ""}, {ID: "ID1"}}}, + {Source: "src5", UIDs: []openrtb2.UID{{ID: ""}, {ID: ""}}}, + }, + expected: []openrtb2.EID{ + {Source: "src3", UIDs: []openrtb2.UID{{ID: "ID1"}, {ID: "ID2"}}}, + {Source: "src4", UIDs: []openrtb2.UID{{ID: "ID1"}}}, + }, + numErrors: 4, + expectedErrorMessages: []string{ + "request.user.eids[1].uids[0] removed due to empty ids", + "request.user.eids[2].uids[0] removed due to empty ids", + "request.user.eids[2].uids[1] removed due to empty ids", + "request.user.eids[2] (source: src5) removed due to empty uids", + }, + }, + { + name: "one-eid-many-uid-empty", + input: []openrtb2.EID{ + {Source: "src6", UIDs: []openrtb2.UID{{ID: ""}, {ID: ""}}}, + }, + expected: []openrtb2.EID{}, + numErrors: 3, + expectedErrorMessages: []string{ + "request.user.eids[0].uids[0] removed due to empty ids", + "request.user.eids[0].uids[1] removed due to empty ids", + "request.user.eids[0] (source: src6) removed due to empty uids", + }, + }, + { + name: "eid_nil", + input: nil, + expected: nil, + numErrors: 0, + expectedErrorMessages: nil, + }, + { + name: "eid_uid_nil", + input: []openrtb2.EID{ + {Source: "src7", UIDs: nil}, + }, + expected: []openrtb2.EID{}, + numErrors: 1, + expectedErrorMessages: []string{ + "request.user.eids[0] (source: src7) removed due to empty uids", + }, + }, + { + name: "source_missing", + input: []openrtb2.EID{ + {UIDs: []openrtb2.UID{{ID: "id1"}}}, + }, + expected: []openrtb2.EID{}, + numErrors: 1, + expectedErrorMessages: []string{ + "request.user.eids[0] removed due to missing source", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + validEIDs, errorsList := validateEIDs(tc.input) + + assert.ElementsMatch(t, tc.expected, validEIDs) + assert.Equal(t, tc.numErrors, len(errorsList)) + + // Assert error messages + assert.Equal(t, len(tc.expectedErrorMessages), len(errorsList)) + for _, err := range errorsList { + assert.Contains(t, tc.expectedErrorMessages, err.Error()) + } + + }) + } +} + +func TestValidateUIDs(t *testing.T) { + testCases := []struct { + name string + input []openrtb2.UID + expectedValidUIDs []openrtb2.UID + expectedErrors []error + }{ + { + name: "many-uid-valid", + input: []openrtb2.UID{ + {ID: "id1"}, + {ID: "id2"}, + }, + expectedValidUIDs: []openrtb2.UID{ + {ID: "id1"}, + {ID: "id2"}, + }, + expectedErrors: nil, + }, + { + name: "many-uid-empty", + input: []openrtb2.UID{ + {ID: ""}, + {ID: ""}, + }, + expectedValidUIDs: nil, + expectedErrors: []error{ + &errortypes.Warning{ + Message: "request.user.eids[0].uids[0] removed due to empty ids", + WarningCode: errortypes.InvalidUserUIDsWarningCode, + }, + &errortypes.Warning{ + Message: "request.user.eids[0].uids[1] removed due to empty ids", + WarningCode: errortypes.InvalidUserUIDsWarningCode, + }, + }, + }, + { + name: "many-mixed", + input: []openrtb2.UID{ + {ID: "id1"}, + {ID: ""}, + {ID: "id2"}, + {ID: ""}, + }, + expectedValidUIDs: []openrtb2.UID{ + {ID: "id1"}, + {ID: "id2"}, + }, + expectedErrors: []error{ + &errortypes.Warning{ + Message: "request.user.eids[0].uids[1] removed due to empty ids", + WarningCode: errortypes.InvalidUserUIDsWarningCode, + }, + &errortypes.Warning{ + Message: "request.user.eids[0].uids[3] removed due to empty ids", + WarningCode: errortypes.InvalidUserUIDsWarningCode, + }, + }, + }, + { + name: "empty-uid", + input: []openrtb2.UID{}, + expectedValidUIDs: nil, + expectedErrors: nil, + }, + { + name: "nil-uid", + input: nil, + expectedValidUIDs: nil, + expectedErrors: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + validUIDs, errorsList := validateUIDs(tc.input, 0) + + assert.ElementsMatch(t, tc.expectedValidUIDs, validUIDs) + assert.ElementsMatch(t, tc.expectedErrors, errorsList) + }) + } +} +func TestValidateUser(t *testing.T) { + + testCases := []struct { + name string + req *openrtb_ext.RequestWrapper + expectedErr []error + expectedEids []openrtb2.EID + }{ + { + name: "Valid_user_with_Geo_accuracy", + req: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + Geo: &openrtb2.Geo{ + Accuracy: 10, + }, + }, + }, + }, + expectedErr: nil, + }, + { + name: "Invalid_user_with_negative_Geo_accuracy", + req: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + Geo: &openrtb2.Geo{ + Accuracy: -10, + }, + }, + }, + }, + expectedErr: []error{errors.New("request.user.geo.accuracy must be a positive number")}, + }, + { + name: "Invalid_user.ext.prebid_with_empty_buyeruids", + req: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + Ext: json.RawMessage(`{"prebid": {"buyeruids": {}}}`), + }, + }, + }, + expectedErr: []error{errors.New(`request.user.ext.prebid requires a "buyeruids" property with at least one ID defined. If none exist, then request.user.ext.prebid should not be defined.`)}, + }, + { + name: "Invalid_user.eids_with_empty_id", + req: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + EIDs: []openrtb2.EID{ + { + Source: "source", + UIDs: []openrtb2.UID{ + {ID: ""}, + }, + }, + }, + }, + }, + }, + expectedErr: []error{&errortypes.Warning{ + Message: "request.user.eids[0].uids[0] removed due to empty ids", + WarningCode: errortypes.InvalidUserUIDsWarningCode, + }, &errortypes.Warning{ + Message: "request.user.eids[0] (source: source) removed due to empty uids", + WarningCode: errortypes.InvalidUserEIDsWarningCode, + }}, + expectedEids: nil, + }, + { + name: "Valid_user.eids_with_UID1_id", + req: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + EIDs: []openrtb2.EID{ + { + Source: "source", + UIDs: []openrtb2.UID{ + {ID: "UID1"}, + }, + }, + }, + }, + }, + }, + expectedErr: nil, + expectedEids: []openrtb2.EID{ + { + Source: "source", + UIDs: []openrtb2.UID{ + {ID: "UID1"}, + }, + }, + }, + }, + { + name: "user.eids_with_empty_UIDs", + req: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + EIDs: []openrtb2.EID{ + { + Source: "source", + UIDs: []openrtb2.UID{ + {}, + }, + }, + }, + }, + }, + }, + expectedErr: []error{ + &errortypes.Warning{ + Message: "request.user.eids[0].uids[0] removed due to empty ids", + WarningCode: errortypes.InvalidUserUIDsWarningCode, + }, + &errortypes.Warning{ + Message: "request.user.eids[0] (source: source) removed due to empty uids", + WarningCode: errortypes.InvalidUserEIDsWarningCode, + }, + }, + expectedEids: nil, + }, + { + name: "user.eids_with_empty_UIDs", + req: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + EIDs: []openrtb2.EID{ + { + Source: "source", + UIDs: []openrtb2.UID{}, + }, + }, + }, + }, + }, + expectedErr: []error{ + &errortypes.Warning{ + Message: "request.user.eids[0] (source: source) removed due to empty uids", + WarningCode: errortypes.InvalidUserEIDsWarningCode, + }, + }, + expectedEids: nil, + }, + { + name: "user.eids_with_No_UIDs", + req: &openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + User: &openrtb2.User{ + EIDs: []openrtb2.EID{ + { + Source: "source", + }, + }, + }, + }, + }, + expectedErr: []error{ + &errortypes.Warning{ + Message: "request.user.eids[0] (source: source) removed due to empty uids", + WarningCode: errortypes.InvalidUserEIDsWarningCode, + }, + }, + expectedEids: nil, + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + deps := &endpointDeps{ + bidderMap: map[string]openrtb_ext.BidderName{ + "appnexus": "appnexus", + }, + } + errs := deps.validateUser(test.req, nil, gpplib.GppContainer{}) + assert.Equal(t, test.expectedErr, errs) + if test.req.User != nil { + assert.ElementsMatch(t, test.expectedEids, test.req.User.EIDs) + } + }) + } +} diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/preferred-media-type-not-defined.json b/endpoints/openrtb2/sample-requests/invalid-whole/preferred-media-type-not-defined.json new file mode 100644 index 00000000000..dbf006e7612 --- /dev/null +++ b/endpoints/openrtb2/sample-requests/invalid-whole/preferred-media-type-not-defined.json @@ -0,0 +1,148 @@ +{ + "description": "multiformat request with preferred media type", + "config": { + "mockBidders": [ + { + "bidderName": "appnexus", + "currency": "USD", + "price": 1.00 + }, + { + "bidderName": "pubmatic", + "currency": "USD", + "price": 2.00 + } + ], + "bidderInfoOverrides": { + "appnexus": { + "openrtb": { + "multiformat-supported": false + } + }, + "pubmatic": { + "openrtb": { + "multiformat-supported": false + } + } + } + }, + "mockBidRequest": { + "id": "some-request-id", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "video": { + "w": 640, + "h": 480, + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, 3, 5, 6 + ] + }, + "ext": { + "appnexus": { + "placementId": 12883451 + }, + "pubmatic": { + "publisherId": "123" + } + } + } + ], + "tmax": 500, + "ext": { + "prebid": { + "biddercontrols":{ + "appnexus":{ + "prefmtype":"banner" + } + } + } + } + }, + "expectedMockBidderRequests": { + "appnexus": { + "id": "some-request-id", + "site": { + "page": "prebid.org", + "ext": { + "amp": 0 + } + }, + "at": 1, + "device": { + "ip": "192.0.2.1" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": 12883451 + } + }, + "secure": 1 + } + ], + "tmax": 500 + } + }, + "expectedBidResponse": { + "id": "some-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "appnexus-bid", + "impid": "some-impression-id", + "price": 1.0, + "ext": { + "origbidcpm": 1.0, + "origbidcur": "USD", + "prebid": { + "meta": { + "adaptercode": "appnexus" + }, + "type": "banner" + } + } + } + ], + "seat": "appnexus" + } + ], + "bidid": "test bid id", + "cur": "USD", + "nbr": 0 + }, + "expectedReturnCode": 200 + } \ No newline at end of file diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-eids-uids-missing.json b/endpoints/openrtb2/sample-requests/invalid-whole/user-eids-uids-missing.json deleted file mode 100644 index 3e55c33b849..00000000000 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-eids-uids-missing.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "description": "Bid request with user.eids array element array element that does not contain uids", - "mockBidRequest": { - "id": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5", - "site": { - "page": "prebid.org", - "publisher": { - "id": "a3de7af2-a86a-4043-a77b-c7e86744155e" - } - }, - "source": { - "tid": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5" - }, - "tmax": 1000, - "imp": [{ - "id": "/19968336/header-bid-tag-0", - "ext": { - "appnexus": { - "placementId": 12883451 - } - }, - "banner": { - "format": [{ - "w": 300, - "h": 250 - }, - { - "w": 300, - "h": 300 - } - ] - } - }], - "regs": { - "ext": { - "gdpr": 1 - } - }, - "user": { - "eids": [{ - "source": "source1" - }] - } - }, - "expectedReturnCode": 400, - "expectedErrorMessage": "Invalid request: request.user.eids[0].uids must contain at least one element or be undefined\n" -} \ No newline at end of file diff --git a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/all-ext.json b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/all-ext.json index 556a04fbec8..98a05bfb788 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/all-ext.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/all-ext.json @@ -96,6 +96,17 @@ } ] } + }, + "biddercontrols":{ + "appnexus": { + "prefmtype": "banner" + }, + "districtm": { + "prefmtype": "video" + }, + "rubicon": { + "prefmtype": "native" + } } } } diff --git a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/dooh.json b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/dooh.json index faa9a7f6646..8990fbc4d93 100644 --- a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/dooh.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/dooh.json @@ -3,7 +3,16 @@ "config": { "mockBidders": [ {"bidderName": "appnexus", "currency": "USD", "price": 0.00} - ] + ], + "bidderInfoOverrides":{ + "appnexus": { + "capabilities": { + "dooh": { + "mediaTypes": ["banner"] + } + } + } + } }, "mockBidRequest": { "id": "some-request-id", diff --git a/endpoints/openrtb2/sample-requests/valid-whole/exemplary/preferred-media-type.json b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/preferred-media-type.json new file mode 100644 index 00000000000..5dd9a0bd221 --- /dev/null +++ b/endpoints/openrtb2/sample-requests/valid-whole/exemplary/preferred-media-type.json @@ -0,0 +1,206 @@ +{ + "description": "multiformat request with preferred media type", + "config": { + "mockBidders": [ + { + "bidderName": "appnexus", + "currency": "USD", + "price": 1.00 + }, + { + "bidderName": "pubmatic", + "currency": "USD", + "price": 2.00 + } + ], + "bidderInfoOverrides": { + "appnexus": { + "openrtb": { + "multiformat-supported": false + } + }, + "pubmatic": { + "openrtb": { + "multiformat-supported": false + } + } + }, + "preferredmediatype":{ + "pubmatic" : "video" + } + }, + "mockBidRequest": { + "id": "some-request-id", + "site": { + "page": "prebid.org" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "video": { + "w": 640, + "h": 480, + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, 3, 5, 6 + ] + }, + "ext": { + "appnexus": { + "placementId": 12883451 + }, + "pubmatic": { + "publisherId": "123" + } + } + } + ], + "tmax": 500, + "ext": { + "prebid": { + "biddercontrols":{ + "appnexus":{ + "prefmtype":"banner" + } + } + } + } + }, + "expectedMockBidderRequests": { + "appnexus": { + "id": "some-request-id", + "site": { + "page": "prebid.org", + "ext": { + "amp": 0 + } + }, + "at": 1, + "device": { + "ip": "192.0.2.1" + }, + "imp": [ + { + "id": "some-impression-id", + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 600 + } + ] + }, + "ext": { + "bidder": { + "placementId": 12883451 + } + }, + "secure": 1 + } + ], + "tmax": 500 + }, + "pubmatic": { + "id": "some-request-id", + "site": { + "page": "prebid.org", + "ext": { + "amp": 0 + } + }, + "at": 1, + "device": { + "ip": "192.0.2.1" + }, + "imp": [ + { + "id": "some-impression-id", + "video": { + "w": 640, + "h": 480, + "mimes": [ + "video/mp4" + ], + "protocols": [ + 2, 3, 5, 6 + ] + }, + "ext": { + "bidder": { + "publisherId": "123" + } + }, + "secure": 1 + } + ], + "tmax": 500 + } + }, + "expectedBidResponse": { + "id": "some-request-id", + "seatbid": [ + { + "bid": [ + { + "id": "appnexus-bid", + "impid": "some-impression-id", + "price": 1.0, + "ext": { + "origbidcpm": 1.0, + "origbidcur": "USD", + "prebid": { + "meta": { + "adaptercode": "appnexus" + }, + "type": "banner" + } + } + } + ], + "seat": "appnexus" + }, + { + "bid": [ + { + "id": "pubmatic-bid", + "impid": "some-impression-id", + "price": 2.0, + "ext": { + "origbidcpm": 2.0, + "origbidcur": "USD", + "prebid": { + "meta": { + "adaptercode": "pubmatic" + }, + "type": "banner" + } + } + } + ], + "seat": "pubmatic" + } + ], + "bidid": "test bid id", + "cur": "USD", + "nbr": 0 + }, + "expectedReturnCode": 200 + } \ No newline at end of file diff --git a/endpoints/openrtb2/sample-requests/valid-whole/user-eids-empty-uids-removed.json b/endpoints/openrtb2/sample-requests/valid-whole/user-eids-empty-uids-removed.json new file mode 100644 index 00000000000..9a4e1373d1f --- /dev/null +++ b/endpoints/openrtb2/sample-requests/valid-whole/user-eids-empty-uids-removed.json @@ -0,0 +1,101 @@ +{ + "description": "Bid request where a request.user.eids.uids are removed when uid is empty, ensuring no bids are returned.", + "mockBidRequest": { + "id": "anyRequestID", + "site": { + "page": "prebid.org", + "publisher": { + "id": "anyPublisher" + } + }, + "imp": [ + { + "id": "anyImpID", + "ext": { + "appnexus": { + "placementId": 42 + } + }, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 300 + } + ] + } + } + ], + "tmax": 1000, + "user": { + "eids": [ + { + "source": "source-1", + "uids": [ + { + "id": "" + }, + { + "id": "id-a" + } + ] + }, + { + "source": "source-2", + "uids": [ + { + "id": "id-b" + } + ] + }, + { + "source": "source-3", + "uids": [ + { + "id": "" + }, + { + "id": "" + } + ] + } + ] + } + }, + "expectedReturnCode": 200, + "expectedBidResponse": { + "id": "anyRequestID", + "cur": "USD", + "seatbid": [], + "ext": { + "warnings": { + "general": [ + { + "code": 10013, + "message": "debug turned off for account" + }, + { + "code": 10013, + "message": "request.user.eids[0].uids[0] removed due to empty ids" + }, + { + "code": 10013, + "message": "request.user.eids[2].uids[0] removed due to empty ids" + }, + { + "code": 10013, + "message": "request.user.eids[2].uids[1] removed due to empty ids" + }, + { + "code": 10013, + "message": "request.user.eids[2] (source: source-3) removed due to empty uids" + } + ] + } + } + } +} \ No newline at end of file diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-eids-source-empty.json b/endpoints/openrtb2/sample-requests/valid-whole/user-eids-source-empty.json similarity index 76% rename from endpoints/openrtb2/sample-requests/invalid-whole/user-eids-source-empty.json rename to endpoints/openrtb2/sample-requests/valid-whole/user-eids-source-empty.json index 902a2d9c1b6..fc770b5d9ae 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-eids-source-empty.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/user-eids-source-empty.json @@ -36,6 +36,13 @@ }] } }, - "expectedReturnCode": 400, - "expectedErrorMessage": "Invalid request: request.user.eids[0] missing required field: \"source\"\n" + "expectedReturnCode": 200, + "expectedBidResponse": { + "ext": { + "warnings": { + "source": "prebid-server", + "message": "request.user.eids[0] missing required field: source" + } + } + } } \ No newline at end of file diff --git a/endpoints/openrtb2/sample-requests/invalid-whole/user-eids-uids-id-empty.json b/endpoints/openrtb2/sample-requests/valid-whole/user-eids-uids-empty.json similarity index 77% rename from endpoints/openrtb2/sample-requests/invalid-whole/user-eids-uids-id-empty.json rename to endpoints/openrtb2/sample-requests/valid-whole/user-eids-uids-empty.json index c8eb07aa335..64d55492d9d 100644 --- a/endpoints/openrtb2/sample-requests/invalid-whole/user-eids-uids-id-empty.json +++ b/endpoints/openrtb2/sample-requests/valid-whole/user-eids-uids-empty.json @@ -29,12 +29,12 @@ }], "tmax": 1000, "user": { - "eids": [{ + "eids": [{ "source": "source1", - "uids": [{}] - }] - } + "uids": [] + }] +} }, - "expectedReturnCode": 400, - "expectedErrorMessage": "Invalid request: request.user.eids[0].uids[0] missing required field: \"id\"\n" + "expectedReturnCode": 200, + "expectedErrorMessage": "request.user.eids[0] (source: source1) removed due to empty uids" } \ No newline at end of file diff --git a/endpoints/openrtb2/sample-requests/valid-whole/user-eids-uids-missing.json b/endpoints/openrtb2/sample-requests/valid-whole/user-eids-uids-missing.json new file mode 100644 index 00000000000..e33a8495a2a --- /dev/null +++ b/endpoints/openrtb2/sample-requests/valid-whole/user-eids-uids-missing.json @@ -0,0 +1,65 @@ +{ + "description": "Bid request with user.eids array element array element that does not contain uids", + "mockBidRequest": { + "id": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5", + "site": { + "page": "prebid.org", + "publisher": { + "id": "a3de7af2-a86a-4043-a77b-c7e86744155e" + } + }, + "source": { + "tid": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5" + }, + "tmax": 1000, + "imp": [ + { + "id": "/19968336/header-bid-tag-0", + "ext": { + "appnexus": { + "placementId": 12883451 + } + }, + "banner": { + "format": [ + { + "w": 300, + "h": 250 + }, + { + "w": 300, + "h": 300 + } + ] + } + } + ], + "regs": { + "ext": { + "gdpr": 1 + } + }, + "user": { + "eids": [ + { + "source": "source1" + } + ] + } + }, + "expectedReturnCode": 200, + "expectedBidResponse": { + "id": "b9c97a4b-cbc4-483d-b2c4-58a19ed5cfc5", + "cur": "USD", + "ext": { + "warnings": { + "general": [ + { + "code": 10013, + "message": "request.user.eids[0] (source: source1) removed due to empty uids" + } + ] + } + } + } +} \ No newline at end of file diff --git a/endpoints/openrtb2/test_utils.go b/endpoints/openrtb2/test_utils.go index e869ded80b8..b19cb5badab 100644 --- a/endpoints/openrtb2/test_utils.go +++ b/endpoints/openrtb2/test_utils.go @@ -41,7 +41,7 @@ import ( "github.com/prebid/prebid-server/v3/util/iputil" "github.com/prebid/prebid-server/v3/util/jsonutil" "github.com/prebid/prebid-server/v3/util/uuidutil" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" ) // In this file we define: @@ -93,12 +93,27 @@ type testConfigValues struct { MockBidders []mockBidderHandler `json:"mockBidders"` RealParamsValidator bool `json:"realParamsValidator"` BidderInfos map[string]bidderInfoOverrides `json:"bidderInfoOverrides"` + PreferredMediaType openrtb_ext.PreferredMediaType `json:"preferredmediatype"` } type bidderInfoOverrides struct { - OpenRTB *OpenRTBInfo `json:"openrtb"` + OpenRTB *OpenRTBInfo `json:"openrtb"` + Capabilities *CapabilitiesInfo `json:"capabilities"` } type OpenRTBInfo struct { - Version string `json:"version"` + Version string `json:"version"` + MultiformatSupported *bool `json:"multiformat-supported"` +} + +// CapabilitiesInfo specifies the supported platforms for a bidder. +type CapabilitiesInfo struct { + App *PlatformInfo `json:"app" mapstructure:"app"` + Site *PlatformInfo `json:"site" mapstructure:"site"` + DOOH *PlatformInfo `json:"dooh" mapstructure:"dooh"` +} + +// PlatformInfo specifies the supported media types for a bidder. +type PlatformInfo struct { + MediaTypes []openrtb_ext.BidType `yaml:"mediaTypes" mapstructure:"mediaTypes"` } type brokenExchange struct{} @@ -1224,13 +1239,20 @@ func buildTestExchange(testCfg *testConfigValues, adapterMap map[openrtb_ext.Bid if len(testCfg.MockBidders) == 0 { testCfg.MockBidders = append(testCfg.MockBidders, mockBidderHandler{BidderName: "appnexus", Currency: "USD", Price: 0.00}) } + singleFormatBidders := make(map[openrtb_ext.BidderName]struct{}) for _, mockBidder := range testCfg.MockBidders { bidServer := httptest.NewServer(http.HandlerFunc(mockBidder.bid)) - bidderAdapter := mockAdapter{mockServerURL: bidServer.URL, seat: mockBidder.Seat} + bidderAdapter := &mockAdapter{mockServerURL: bidServer.URL, seat: mockBidder.Seat} bidderName := openrtb_ext.BidderName(mockBidder.BidderName) - adapterMap[bidderName] = exchange.AdaptBidder(&bidderAdapter, bidServer.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, bidderName, nil, "") + infoAwareBidderAdapter := adapters.BuildInfoAwareBidder(bidderAdapter, bidderInfos[string(bidderName)]) + + adapterMap[bidderName] = exchange.AdaptBidder(infoAwareBidderAdapter, bidServer.Client(), &config.Configuration{}, &metricsConfig.NilMetricsEngine{}, bidderName, nil, "") mockBidServersArray = append(mockBidServersArray, bidServer) + + if bidderInfo := bidderInfos[string(bidderName)]; bidderInfo.OpenRTB != nil && bidderInfo.OpenRTB.MultiformatSupported != nil && !*bidderInfo.OpenRTB.MultiformatSupported { + singleFormatBidders[bidderName] = struct{}{} + } } mockCurrencyConverter := currency.NewRateConverter(mockCurrencyRatesServer.Client(), mockCurrencyRatesServer.URL, time.Second) @@ -1241,7 +1263,6 @@ func buildTestExchange(testCfg *testConfigValues, adapterMap map[openrtb_ext.Bid }.Builder testExchange := exchange.NewExchange(adapterMap, - &wellBehavedCache{}, cfg, requestValidator, @@ -1254,6 +1275,7 @@ func buildTestExchange(testCfg *testConfigValues, adapterMap map[openrtb_ext.Bid &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, + singleFormatBidders, ) testExchange = &exchangeTestWrapper{ @@ -1284,11 +1306,38 @@ func buildTestEndpoint(test testCase, cfg *config.Configuration) (httprouter.Han bidderInfos, _ := config.LoadBidderInfoFromDisk("../../static/bidder-info") for bidder, overrides := range test.Config.BidderInfos { if bi, ok := bidderInfos[bidder]; ok { - if overrides.OpenRTB != nil && len(overrides.OpenRTB.Version) > 0 { + if overrides.OpenRTB != nil || overrides.Capabilities != nil { if bi.OpenRTB == nil { bi.OpenRTB = &config.OpenRTBInfo{} } - bi.OpenRTB.Version = overrides.OpenRTB.Version + if overrides.OpenRTB != nil { + if len(overrides.OpenRTB.Version) > 0 { + bi.OpenRTB.Version = overrides.OpenRTB.Version + } + if overrides.OpenRTB.MultiformatSupported != nil { + bi.OpenRTB.MultiformatSupported = overrides.OpenRTB.MultiformatSupported + } + } + if overrides.Capabilities != nil { + if bi.Capabilities == nil { + bi.Capabilities = &config.CapabilitiesInfo{} + } + + if overrides.Capabilities.Site != nil { + bi.Capabilities.Site = &config.PlatformInfo{} + bi.Capabilities.Site.MediaTypes = overrides.Capabilities.Site.MediaTypes + } + + if overrides.Capabilities.App != nil { + bi.Capabilities.App = &config.PlatformInfo{} + bi.Capabilities.App.MediaTypes = overrides.Capabilities.App.MediaTypes + } + + if overrides.Capabilities.DOOH != nil { + bi.Capabilities.DOOH = &config.PlatformInfo{} + bi.Capabilities.DOOH.MediaTypes = overrides.Capabilities.DOOH.MediaTypes + } + } bidderInfos[bidder] = bi } } diff --git a/endpoints/openrtb2/video_auction.go b/endpoints/openrtb2/video_auction.go index cf18840fbd6..f3dbd2246c0 100644 --- a/endpoints/openrtb2/video_auction.go +++ b/endpoints/openrtb2/video_auction.go @@ -21,7 +21,7 @@ import ( "github.com/prebid/prebid-server/v3/hooks/hookexecution" "github.com/prebid/prebid-server/v3/ortb" "github.com/prebid/prebid-server/v3/privacy" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" accountService "github.com/prebid/prebid-server/v3/account" "github.com/prebid/prebid-server/v3/analytics" diff --git a/errortypes/code.go b/errortypes/code.go index 49cb6d4bcf9..0b194d0830d 100644 --- a/errortypes/code.go +++ b/errortypes/code.go @@ -35,6 +35,8 @@ const ( InvalidBidResponseDSAWarningCode SecCookieDeprecationLenWarningCode SecBrowsingTopicsWarningCode + InvalidUserEIDsWarningCode + InvalidUserUIDsWarningCode ) // Coder provides an error or warning code with severity. diff --git a/exchange/adapter_builders.go b/exchange/adapter_builders.go index 7647de71786..87821fd0c75 100755 --- a/exchange/adapter_builders.go +++ b/exchange/adapter_builders.go @@ -140,6 +140,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/loyal" "github.com/prebid/prebid-server/v3/adapters/lunamedia" "github.com/prebid/prebid-server/v3/adapters/mabidder" + "github.com/prebid/prebid-server/v3/adapters/madsense" "github.com/prebid/prebid-server/v3/adapters/madvertise" "github.com/prebid/prebid-server/v3/adapters/marsmedia" "github.com/prebid/prebid-server/v3/adapters/mediago" @@ -153,6 +154,7 @@ import ( "github.com/prebid/prebid-server/v3/adapters/missena" "github.com/prebid/prebid-server/v3/adapters/mobfoxpb" "github.com/prebid/prebid-server/v3/adapters/mobilefuse" + "github.com/prebid/prebid-server/v3/adapters/mobkoi" "github.com/prebid/prebid-server/v3/adapters/motorik" "github.com/prebid/prebid-server/v3/adapters/nativo" "github.com/prebid/prebid-server/v3/adapters/nextmillennium" @@ -389,6 +391,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderLoyal: loyal.Builder, openrtb_ext.BidderLunaMedia: lunamedia.Builder, openrtb_ext.BidderMabidder: mabidder.Builder, + openrtb_ext.BidderMadSense: madsense.Builder, openrtb_ext.BidderMadvertise: madvertise.Builder, openrtb_ext.BidderMarsmedia: marsmedia.Builder, openrtb_ext.BidderMediafuse: appnexus.Builder, @@ -403,6 +406,7 @@ func newAdapterBuilders() map[openrtb_ext.BidderName]adapters.Builder { openrtb_ext.BidderMissena: missena.Builder, openrtb_ext.BidderMobfoxpb: mobfoxpb.Builder, openrtb_ext.BidderMobileFuse: mobilefuse.Builder, + openrtb_ext.BidderMobkoi: mobkoi.Builder, openrtb_ext.BidderMotorik: motorik.Builder, openrtb_ext.BidderNativo: nativo.Builder, openrtb_ext.BidderNextMillennium: nextmillennium.Builder, diff --git a/exchange/adapter_util.go b/exchange/adapter_util.go index e70c32055a0..7eadeac0fce 100644 --- a/exchange/adapter_util.go +++ b/exchange/adapter_util.go @@ -10,12 +10,12 @@ import ( "github.com/prebid/prebid-server/v3/openrtb_ext" ) -func BuildAdapters(client *http.Client, cfg *config.Configuration, infos config.BidderInfos, me metrics.MetricsEngine) (map[openrtb_ext.BidderName]AdaptedBidder, []error) { +func BuildAdapters(client *http.Client, cfg *config.Configuration, infos config.BidderInfos, me metrics.MetricsEngine) (map[openrtb_ext.BidderName]AdaptedBidder, map[openrtb_ext.BidderName]struct{}, []error) { server := config.Server{ExternalUrl: cfg.ExternalURL, GvlID: cfg.GDPR.HostVendorID, DataCenter: cfg.DataCenter} - bidders, errs := buildBidders(infos, newAdapterBuilders(), server) + bidders, singleFormatBidders, errs := buildBidders(infos, newAdapterBuilders(), server) if len(errs) > 0 { - return nil, errs + return nil, nil, errs } exchangeBidders := make(map[openrtb_ext.BidderName]AdaptedBidder, len(bidders)) @@ -25,11 +25,12 @@ func BuildAdapters(client *http.Client, cfg *config.Configuration, infos config. exchangeBidder = addValidatedBidderMiddleware(exchangeBidder) exchangeBidders[bidderName] = exchangeBidder } - return exchangeBidders, nil + return exchangeBidders, singleFormatBidders, nil } -func buildBidders(infos config.BidderInfos, builders map[openrtb_ext.BidderName]adapters.Builder, server config.Server) (map[openrtb_ext.BidderName]adapters.Bidder, []error) { +func buildBidders(infos config.BidderInfos, builders map[openrtb_ext.BidderName]adapters.Builder, server config.Server) (map[openrtb_ext.BidderName]adapters.Bidder, map[openrtb_ext.BidderName]struct{}, []error) { bidders := make(map[openrtb_ext.BidderName]adapters.Bidder) + singleFormatBidders := make(map[openrtb_ext.BidderName]struct{}) var errs []error for bidder, info := range infos { @@ -61,9 +62,12 @@ func buildBidders(infos config.BidderInfos, builders map[openrtb_ext.BidderName] continue } bidders[bidderName] = adapters.BuildInfoAwareBidder(bidderInstance, info) + if !adapters.IsMultiFormatSupported(info) { + singleFormatBidders[bidderName] = struct{}{} + } } } - return bidders, errs + return bidders, singleFormatBidders, errs } func setAliasBuilder(info config.BidderInfo, builders map[openrtb_ext.BidderName]adapters.Builder, bidderName openrtb_ext.BidderName) error { diff --git a/exchange/adapter_util_test.go b/exchange/adapter_util_test.go index 3f558af5610..e6da2f8e7c6 100644 --- a/exchange/adapter_util_test.go +++ b/exchange/adapter_util_test.go @@ -17,8 +17,15 @@ import ( ) var ( - infoEnabled = config.BidderInfo{Disabled: false} - infoDisabled = config.BidderInfo{Disabled: true} + falseValue = false + infoEnabled = config.BidderInfo{Disabled: false} + infoDisabled = config.BidderInfo{Disabled: true} + multiformatDisabled = config.BidderInfo{ + Disabled: false, + OpenRTB: &config.OpenRTBInfo{ + MultiformatSupported: &falseValue, + }, + } ) func TestBuildAdapters(t *testing.T) { @@ -36,15 +43,17 @@ func TestBuildAdapters(t *testing.T) { rubiconBidderValidated := addValidatedBidderMiddleware(rubiconBidderAdapted) testCases := []struct { - description string - bidderInfos map[string]config.BidderInfo - expectedBidders map[openrtb_ext.BidderName]AdaptedBidder - expectedErrors []error + description string + bidderInfos map[string]config.BidderInfo + expectedBidders map[openrtb_ext.BidderName]AdaptedBidder + expectedSingleFormatBidders map[openrtb_ext.BidderName]struct{} + expectedErrors []error }{ { - description: "No Bidders", - bidderInfos: map[string]config.BidderInfo{}, - expectedBidders: map[openrtb_ext.BidderName]AdaptedBidder{}, + description: "No Bidders", + bidderInfos: map[string]config.BidderInfo{}, + expectedBidders: map[openrtb_ext.BidderName]AdaptedBidder{}, + expectedSingleFormatBidders: map[openrtb_ext.BidderName]struct{}{}, }, { description: "One Bidder", @@ -52,6 +61,7 @@ func TestBuildAdapters(t *testing.T) { expectedBidders: map[openrtb_ext.BidderName]AdaptedBidder{ openrtb_ext.BidderAppnexus: appnexusValidated, }, + expectedSingleFormatBidders: map[openrtb_ext.BidderName]struct{}{}, }, { description: "Many Bidders", @@ -60,6 +70,7 @@ func TestBuildAdapters(t *testing.T) { openrtb_ext.BidderAppnexus: appnexusValidated, openrtb_ext.BidderRubicon: rubiconBidderValidated, }, + expectedSingleFormatBidders: map[openrtb_ext.BidderName]struct{}{}, }, { description: "Invalid - Builder Errors", @@ -67,13 +78,29 @@ func TestBuildAdapters(t *testing.T) { expectedErrors: []error{ errors.New("unknown: unknown bidder"), }, + expectedSingleFormatBidders: nil, + }, + { + description: "Bidders with multiformat Support Disabled", + bidderInfos: map[string]config.BidderInfo{"appnexus": multiformatDisabled, "rubicon": multiformatDisabled}, + expectedBidders: map[openrtb_ext.BidderName]AdaptedBidder{ + openrtb_ext.BidderAppnexus: appnexusValidated, + openrtb_ext.BidderRubicon: rubiconBidderValidated, + }, + expectedSingleFormatBidders: map[openrtb_ext.BidderName]struct{}{ + openrtb_ext.BidderAppnexus: {}, + openrtb_ext.BidderRubicon: {}, + }, }, } cfg := &config.Configuration{} for _, test := range testCases { - bidders, errs := BuildAdapters(client, cfg, test.bidderInfos, metricEngine) + bidders, singleFormatBidders, errs := BuildAdapters(client, cfg, test.bidderInfos, metricEngine) assert.Equal(t, test.expectedBidders, bidders, test.description+":bidders") + + assert.Equal(t, test.expectedSingleFormatBidders, singleFormatBidders, test.description+":singleFormatBidders") + assert.ElementsMatch(t, test.expectedErrors, errs, test.description+":errors") } } @@ -152,7 +179,7 @@ func TestBuildBidders(t *testing.T) { } for _, test := range testCases { - bidders, errs := buildBidders(test.bidderInfos, test.builders, server) + bidders, _, errs := buildBidders(test.bidderInfos, test.builders, server) // For Test Setup Convenience if test.expectedBidders == nil { diff --git a/exchange/events.go b/exchange/events.go index d52db53aac6..20150f90b97 100644 --- a/exchange/events.go +++ b/exchange/events.go @@ -4,7 +4,7 @@ import ( "time" "github.com/prebid/prebid-server/v3/exchange/entities" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" "github.com/prebid/prebid-server/v3/analytics" "github.com/prebid/prebid-server/v3/config" diff --git a/exchange/exchange.go b/exchange/exchange.go index daddf9debc2..4fd35279f23 100644 --- a/exchange/exchange.go +++ b/exchange/exchange.go @@ -85,6 +85,7 @@ type exchange struct { macroReplacer macros.Replacer priceFloorEnabled bool priceFloorFetcher floors.FloorFetcher + singleFormatBidders map[openrtb_ext.BidderName]struct{} } // Container to pass out response ext data from the GetAllBids goroutines back into the main thread @@ -136,7 +137,7 @@ func (randomDeduplicateBidBooleanGenerator) Generate() bool { return rand.Intn(100) < 50 } -func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid_cache_client.Client, cfg *config.Configuration, requestValidator ortb.RequestValidator, syncersByBidder map[string]usersync.Syncer, metricsEngine metrics.MetricsEngine, infos config.BidderInfos, gdprPermsBuilder gdpr.PermissionsBuilder, currencyConverter *currency.RateConverter, categoriesFetcher stored_requests.CategoryFetcher, adsCertSigner adscert.Signer, macroReplacer macros.Replacer, priceFloorFetcher floors.FloorFetcher) Exchange { +func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid_cache_client.Client, cfg *config.Configuration, requestValidator ortb.RequestValidator, syncersByBidder map[string]usersync.Syncer, metricsEngine metrics.MetricsEngine, infos config.BidderInfos, gdprPermsBuilder gdpr.PermissionsBuilder, currencyConverter *currency.RateConverter, categoriesFetcher stored_requests.CategoryFetcher, adsCertSigner adscert.Signer, macroReplacer macros.Replacer, priceFloorFetcher floors.FloorFetcher, singleFormatBidders map[openrtb_ext.BidderName]struct{}) Exchange { bidderToSyncerKey := map[string]string{} for bidder, syncer := range syncersByBidder { bidderToSyncerKey[bidder] = syncer.Key() @@ -184,6 +185,7 @@ func NewExchange(adapters map[openrtb_ext.BidderName]AdaptedBidder, cache prebid macroReplacer: macroReplacer, priceFloorEnabled: cfg.PriceFloors.Enabled, priceFloorFetcher: priceFloorFetcher, + singleFormatBidders: singleFormatBidders, } } @@ -401,8 +403,11 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog } else if r.Account.AlternateBidderCodes != nil { alternateBidderCodes = *r.Account.AlternateBidderCodes } + + liveAdaptersPreferredMediaType := getBidderPreferredMediaTypeMap(requestExtPrebid, &r.Account, liveAdapters, e.singleFormatBidders) + var extraRespInfo extraAuctionResponseInfo - adapterBids, adapterExtra, extraRespInfo = e.getAllBids(auctionCtx, bidderRequests, bidAdjustmentFactors, conversions, accountDebugAllow, r.GlobalPrivacyControlHeader, debugLog.DebugOverride, alternateBidderCodes, requestExtLegacy.Prebid.Experiment, r.HookExecutor, r.StartTime, bidAdjustmentRules, r.TmaxAdjustments, responseDebugAllow) + adapterBids, adapterExtra, extraRespInfo = e.getAllBids(auctionCtx, bidderRequests, bidAdjustmentFactors, conversions, accountDebugAllow, r.GlobalPrivacyControlHeader, debugLog.DebugOverride, alternateBidderCodes, requestExtLegacy.Prebid.Experiment, r.HookExecutor, r.StartTime, bidAdjustmentRules, r.TmaxAdjustments, responseDebugAllow, liveAdaptersPreferredMediaType) fledge = extraRespInfo.fledge anyBidsReturned = extraRespInfo.bidsFound r.BidderResponseStartTime = extraRespInfo.bidderResponseStartTime @@ -550,6 +555,41 @@ func (e *exchange) HoldAuction(ctx context.Context, r *AuctionRequest, debugLog }, nil } +// getBidderPreferredMediaType reads the preferred media type from the request and account and returns a map of bidder to preferred media type. Preference given to the request over account. +func getBidderPreferredMediaTypeMap(prebid *openrtb_ext.ExtRequestPrebid, account *config.Account, liveAdapters []openrtb_ext.BidderName, singleFormatBidders map[openrtb_ext.BidderName]struct{}) openrtb_ext.PreferredMediaType { + preferredMediaType := make(openrtb_ext.PreferredMediaType) + + // Skip if no bidders are present in singleFormatBidders + if len(singleFormatBidders) == 0 { + return nil + } + + for _, bidder := range liveAdapters { + + // Skip if the bidder is not present in singleFormatBidders + if _, found := singleFormatBidders[bidder]; !found { + continue + } + + //read preferred media type from request + if prebid != nil && prebid.BidderControls != nil { + if bidderControl, found := prebid.BidderControls[bidder]; found && bidderControl.PreferredMediaType != "" { + preferredMediaType[bidder] = bidderControl.PreferredMediaType + continue + } + } + + // if preferred media type not present in the request, read from account config + if account != nil && account.PreferredMediaType != nil { + if preferredType, found := account.PreferredMediaType[bidder]; found { + preferredMediaType[bidder] = preferredType + } + } + } + + return preferredMediaType +} + func buildMultiBidMap(prebid *openrtb_ext.ExtRequestPrebid) map[string]openrtb_ext.ExtMultiBid { if prebid == nil || prebid.MultiBid == nil { return nil @@ -713,7 +753,8 @@ func (e *exchange) getAllBids( pbsRequestStartTime time.Time, bidAdjustmentRules map[string][]openrtb_ext.Adjustment, tmaxAdjustments *TmaxAdjustmentsPreprocessed, - responseDebugAllowed bool) ( + responseDebugAllowed bool, + liveAdaptersPreferredMediaType openrtb_ext.PreferredMediaType) ( map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid, map[openrtb_ext.BidderName]*seatResponseExtra, extraAuctionResponseInfo) { @@ -746,6 +787,12 @@ func (e *exchange) getAllBids( reqInfo.PbsEntryPoint = bidderRequest.BidderLabels.RType reqInfo.GlobalPrivacyControlHeader = globalPrivacyControlHeader + if len(liveAdaptersPreferredMediaType) > 0 { + if mtype, found := liveAdaptersPreferredMediaType[bidder.BidderName]; found { + reqInfo.PreferredMediaType = mtype + } + } + bidReqOptions := bidRequestOptions{ accountDebugAllowed: accountDebugAllowed, headerDebugAllowed: headerDebugAllowed, diff --git a/exchange/exchange_test.go b/exchange/exchange_test.go index 7edbec64d7e..dcd8dcdec7a 100644 --- a/exchange/exchange_test.go +++ b/exchange/exchange_test.go @@ -46,7 +46,7 @@ import ( "github.com/prebid/prebid-server/v3/util/ptrutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" ) func TestNewExchange(t *testing.T) { @@ -71,7 +71,7 @@ func TestNewExchange(t *testing.T) { t.Fatal(err) } - adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } @@ -84,7 +84,7 @@ func TestNewExchange(t *testing.T) { }, }.Builder - e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) for _, bidderName := range knownAdapters { if _, ok := e.adapterMap[bidderName]; !ok { if biddersInfo[string(bidderName)].IsEnabled() { @@ -121,7 +121,7 @@ func TestCharacterEscape(t *testing.T) { defer server.Close() - adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } @@ -134,7 +134,7 @@ func TestCharacterEscape(t *testing.T) { }, }.Builder - e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) // 3) Build all the parameters e.buildBidResponse(ctx.Background(), liveA... ) needs //liveAdapters []openrtb_ext.BidderName, @@ -1224,7 +1224,7 @@ func TestGetBidCacheInfoEndToEnd(t *testing.T) { t.Fatal(err) } - adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } @@ -1237,7 +1237,7 @@ func TestGetBidCacheInfoEndToEnd(t *testing.T) { }, }.Builder - e := NewExchange(adapters, pbc, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + e := NewExchange(adapters, pbc, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) // 3) Build all the parameters e.buildBidResponse(ctx.Background(), liveA... ) needs liveAdapters := []openrtb_ext.BidderName{bidderName} @@ -1583,7 +1583,7 @@ func TestBidResponseCurrency(t *testing.T) { t.Fatal(err) } - adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } @@ -1596,7 +1596,7 @@ func TestBidResponseCurrency(t *testing.T) { }, }.Builder - e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) liveAdapters := make([]openrtb_ext.BidderName, 1) liveAdapters[0] = "appnexus" @@ -1739,12 +1739,12 @@ func TestBidResponseImpExtInfo(t *testing.T) { biddersInfo := config.BidderInfos{"appnexus": config.BidderInfo{Endpoint: "http://ib.adnxs.com"}} - adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } - e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, nil, gdprPermsBuilder, nil, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, nil, gdprPermsBuilder, nil, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) liveAdapters := make([]openrtb_ext.BidderName, 1) liveAdapters[0] = "appnexus" @@ -1815,7 +1815,7 @@ func TestRaceIntegration(t *testing.T) { t.Fatal(err) } - adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } @@ -1838,7 +1838,7 @@ func TestRaceIntegration(t *testing.T) { }, }.Builder - ex := NewExchange(adapters, &wellBehavedCache{}, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, &nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + ex := NewExchange(adapters, &wellBehavedCache{}, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, &nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) _, err = ex.HoldAuction(context.Background(), auctionRequest, &debugLog) if err != nil { t.Errorf("HoldAuction returned unexpected error: %v", err) @@ -1923,7 +1923,7 @@ func TestPanicRecovery(t *testing.T) { t.Fatal(err) } - adapters, adaptersErr := BuildAdapters(&http.Client{}, cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(&http.Client{}, cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } @@ -1936,7 +1936,7 @@ func TestPanicRecovery(t *testing.T) { }, }.Builder - e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) chBids := make(chan *bidResponseWrapper, 1) panicker := func(bidderRequest BidderRequest, conversions currency.Conversions) { @@ -1989,7 +1989,7 @@ func TestPanicRecoveryHighLevel(t *testing.T) { t.Fatal(err) } - adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } @@ -2006,7 +2006,7 @@ func TestPanicRecoveryHighLevel(t *testing.T) { allowAllBidders: true, }, }.Builder - e := NewExchange(adapters, &mockCache{}, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, categoriesFetcher, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + e := NewExchange(adapters, &mockCache{}, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, categoriesFetcher, &adscert.NilSigner{}, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) e.adapterMap[openrtb_ext.BidderBeachfront] = panicingAdapter{} e.adapterMap[openrtb_ext.BidderAppnexus] = panicingAdapter{} @@ -4571,7 +4571,7 @@ func TestPassExperimentConfigsToHoldAuction(t *testing.T) { signer := MockSigner{} - adapters, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) + adapters, _, adaptersErr := BuildAdapters(server.Client(), cfg, biddersInfo, &metricsConf.NilMetricsEngine{}) if adaptersErr != nil { t.Fatalf("Error intializing adapters: %v", adaptersErr) } @@ -4584,7 +4584,7 @@ func TestPassExperimentConfigsToHoldAuction(t *testing.T) { }, }.Builder - e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &signer, macros.NewStringIndexBasedReplacer(), nil).(*exchange) + e := NewExchange(adapters, nil, cfg, &mockRequestValidator{}, map[string]usersync.Syncer{}, &metricsConf.NilMetricsEngine{}, biddersInfo, gdprPermsBuilder, currencyConverter, nilCategoryFetcher{}, &signer, macros.NewStringIndexBasedReplacer(), nil, nil).(*exchange) // Define mock incoming bid requeset mockBidRequest := &openrtb2.BidRequest{ @@ -5170,19 +5170,20 @@ func TestGetAllBids(t *testing.T) { defer server.Close() type testIn struct { - bidderRequests []BidderRequest - bidAdjustments map[string]float64 - conversions currency.Conversions - accountDebugAllowed bool - globalPrivacyControlHeader string - headerDebugAllowed bool - alternateBidderCodes openrtb_ext.ExtAlternateBidderCodes - experiment *openrtb_ext.Experiment - hookExecutor hookexecution.StageExecutor - pbsRequestStartTime time.Time - bidAdjustmentRules map[string][]openrtb_ext.Adjustment - tmaxAdjustments *TmaxAdjustmentsPreprocessed - adapterMap map[openrtb_ext.BidderName]AdaptedBidder + bidderRequests []BidderRequest + bidAdjustments map[string]float64 + conversions currency.Conversions + accountDebugAllowed bool + globalPrivacyControlHeader string + headerDebugAllowed bool + alternateBidderCodes openrtb_ext.ExtAlternateBidderCodes + experiment *openrtb_ext.Experiment + hookExecutor hookexecution.StageExecutor + pbsRequestStartTime time.Time + bidAdjustmentRules map[string][]openrtb_ext.Adjustment + tmaxAdjustments *TmaxAdjustmentsPreprocessed + adapterMap map[openrtb_ext.BidderName]AdaptedBidder + liveAdaptersPreferredMediaType map[openrtb_ext.BidderName]openrtb_ext.BidType } type testResults struct { adapterBids map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid @@ -5475,7 +5476,7 @@ func TestGetAllBids(t *testing.T) { adapterBids, adapterExtra, extraRespInfo := e.getAllBids(context.Background(), test.in.bidderRequests, test.in.bidAdjustments, test.in.conversions, test.in.accountDebugAllowed, test.in.globalPrivacyControlHeader, test.in.headerDebugAllowed, test.in.alternateBidderCodes, test.in.experiment, - test.in.hookExecutor, test.in.pbsRequestStartTime, test.in.bidAdjustmentRules, test.in.tmaxAdjustments, false) + test.in.hookExecutor, test.in.pbsRequestStartTime, test.in.bidAdjustmentRules, test.in.tmaxAdjustments, false, test.in.liveAdaptersPreferredMediaType) assert.Equalf(t, test.expected.extraRespInfo.bidsFound, extraRespInfo.bidsFound, "extraRespInfo.bidsFound mismatch") assert.Equalf(t, test.expected.adapterBids, adapterBids, "adapterBids mismatch") @@ -6355,6 +6356,163 @@ func TestBidsToUpdate(t *testing.T) { } } +func TestGetBidderPreferredMediaType(t *testing.T) { + tests := []struct { + name string + prebid *openrtb_ext.ExtRequestPrebid + account *config.Account + liveAdapters []openrtb_ext.BidderName + singleFormatBidders map[openrtb_ext.BidderName]struct{} + expected openrtb_ext.PreferredMediaType + }{ + { + name: "Nil account and request preferred media type", + prebid: nil, + account: &config.Account{}, + liveAdapters: []openrtb_ext.BidderName{"bidderA"}, + singleFormatBidders: map[openrtb_ext.BidderName]struct{}{ + "bidderA": {}, + }, + expected: openrtb_ext.PreferredMediaType{}, + }, + { + name: "Account preferred media type only", + prebid: nil, + account: &config.Account{ + PreferredMediaType: map[openrtb_ext.BidderName]openrtb_ext.BidType{ + "bidderA": openrtb_ext.BidTypeBanner, + }, + }, + liveAdapters: []openrtb_ext.BidderName{"bidderA"}, + singleFormatBidders: map[openrtb_ext.BidderName]struct{}{ + "bidderA": {}, + }, + expected: openrtb_ext.PreferredMediaType{ + "bidderA": openrtb_ext.BidTypeBanner, + }, + }, + { + name: "Request preferred media type only", + prebid: &openrtb_ext.ExtRequestPrebid{ + BidderControls: map[openrtb_ext.BidderName]openrtb_ext.BidderControl{ + "bidderB": {PreferredMediaType: openrtb_ext.BidTypeVideo}, + }, + }, + account: &config.Account{}, + liveAdapters: []openrtb_ext.BidderName{"bidderB"}, + singleFormatBidders: map[openrtb_ext.BidderName]struct{}{ + "bidderB": {}, + }, + expected: openrtb_ext.PreferredMediaType{ + "bidderB": openrtb_ext.BidTypeVideo, + }, + }, + { + name: "Account and request preferred media type", + prebid: &openrtb_ext.ExtRequestPrebid{ + BidderControls: map[openrtb_ext.BidderName]openrtb_ext.BidderControl{ + "bidderB": {PreferredMediaType: openrtb_ext.BidTypeVideo}, + }, + }, + account: &config.Account{ + PreferredMediaType: map[openrtb_ext.BidderName]openrtb_ext.BidType{ + "bidderA": openrtb_ext.BidTypeBanner, + }, + }, + liveAdapters: []openrtb_ext.BidderName{"bidderA", "bidderB", "bidderC"}, + singleFormatBidders: map[openrtb_ext.BidderName]struct{}{ + "bidderA": {}, + "bidderB": {}, + }, + expected: openrtb_ext.PreferredMediaType{ + "bidderA": openrtb_ext.BidTypeBanner, + "bidderB": openrtb_ext.BidTypeVideo, + }, + }, + { + name: "Request overrides account preferred media type", + prebid: &openrtb_ext.ExtRequestPrebid{ + BidderControls: map[openrtb_ext.BidderName]openrtb_ext.BidderControl{ + "bidderA": {PreferredMediaType: openrtb_ext.BidTypeVideo}, + }, + }, + account: &config.Account{ + PreferredMediaType: map[openrtb_ext.BidderName]openrtb_ext.BidType{ + "bidderA": openrtb_ext.BidTypeBanner, + }, + }, + liveAdapters: []openrtb_ext.BidderName{"bidderA"}, + singleFormatBidders: map[openrtb_ext.BidderName]struct{}{ + "bidderA": {}, + }, + expected: openrtb_ext.PreferredMediaType{ + "bidderA": openrtb_ext.BidTypeVideo, + }, + }, + { + name: "Bidder not in singleFormatBidders", + prebid: &openrtb_ext.ExtRequestPrebid{ + BidderControls: map[openrtb_ext.BidderName]openrtb_ext.BidderControl{ + "bidderA": {PreferredMediaType: openrtb_ext.BidTypeVideo}, + }, + }, + account: &config.Account{ + PreferredMediaType: map[openrtb_ext.BidderName]openrtb_ext.BidType{ + "bidderA": openrtb_ext.BidTypeBanner, + }, + }, + liveAdapters: []openrtb_ext.BidderName{"bidderA"}, + singleFormatBidders: map[openrtb_ext.BidderName]struct{}{ + "bidderB": {}, + }, + expected: openrtb_ext.PreferredMediaType{}, + }, + { + name: "No bidders in singleFormatBidders", + prebid: &openrtb_ext.ExtRequestPrebid{ + BidderControls: map[openrtb_ext.BidderName]openrtb_ext.BidderControl{ + "bidderA": {PreferredMediaType: openrtb_ext.BidTypeVideo}, + }, + }, + account: &config.Account{ + PreferredMediaType: map[openrtb_ext.BidderName]openrtb_ext.BidType{ + "bidderA": openrtb_ext.BidTypeBanner, + }, + }, + liveAdapters: []openrtb_ext.BidderName{"bidderA"}, + singleFormatBidders: make(map[openrtb_ext.BidderName]struct{}), + expected: nil, + }, + { + name: "Different bidders in singleFormatBidders than liveAdapters", + prebid: &openrtb_ext.ExtRequestPrebid{ + BidderControls: map[openrtb_ext.BidderName]openrtb_ext.BidderControl{ + "bidderA": {PreferredMediaType: openrtb_ext.BidTypeVideo}, + }, + }, + account: &config.Account{ + PreferredMediaType: map[openrtb_ext.BidderName]openrtb_ext.BidType{ + "bidderC": openrtb_ext.BidTypeBanner, + "bidderD": openrtb_ext.BidTypeVideo, + }, + }, + liveAdapters: []openrtb_ext.BidderName{"bidderA", "bidderB"}, + singleFormatBidders: map[openrtb_ext.BidderName]struct{}{ + "bidderC": {}, + "bidderD": {}, + }, + expected: openrtb_ext.PreferredMediaType{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := getBidderPreferredMediaTypeMap(tt.prebid, tt.account, tt.liveAdapters, tt.singleFormatBidders) + assert.Equal(t, tt.expected, result) + }) + } +} + func TestIsEEACountry(t *testing.T) { eeaCountries := []string{"FRA", "DEU", "ITA", "ESP", "NLD"} diff --git a/firstpartydata/first_party_data.go b/firstpartydata/first_party_data.go index 44a3241a53c..a9107efa6fc 100644 --- a/firstpartydata/first_party_data.go +++ b/firstpartydata/first_party_data.go @@ -7,7 +7,7 @@ import ( "strings" "github.com/prebid/openrtb/v20/openrtb2" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" "github.com/prebid/prebid-server/v3/errortypes" "github.com/prebid/prebid-server/v3/openrtb_ext" diff --git a/go.mod b/go.mod index c8e1d25d309..da0f47998e3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/prebid/prebid-server/v3 -go 1.23 +go 1.23.0 retract v3.0.0 // Forgot to update major version in import path and module name @@ -40,10 +40,10 @@ require ( github.com/vrischmann/go-metrics-influxdb v0.1.1 github.com/xeipuuv/gojsonschema v1.2.0 github.com/yudai/gojsondiff v1.0.0 - golang.org/x/net v0.33.0 - golang.org/x/text v0.21.0 + golang.org/x/net v0.38.0 + golang.org/x/text v0.23.0 google.golang.org/grpc v1.56.3 - gopkg.in/evanphx/json-patch.v4 v4.12.0 + gopkg.in/evanphx/json-patch.v5 v5.9.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -78,8 +78,8 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yudai/pp v2.0.1+incompatible // indirect - golang.org/x/crypto v0.31.0 // indirect - golang.org/x/sys v0.28.0 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/sys v0.31.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.66.4 // indirect diff --git a/go.sum b/go.sum index cd2900708bf..5398b2d6b1d 100644 --- a/go.sum +++ b/go.sum @@ -546,8 +546,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -632,8 +632,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -744,8 +744,8 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -758,8 +758,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -987,8 +987,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/evanphx/json-patch.v5 v5.9.0 h1:hx1VU2SGj4F8r9b8GUwJLdc8DNO8sy79ZGui0G05GLo= +gopkg.in/evanphx/json-patch.v5 v5.9.0/go.mod h1:/kvTRh1TVm5wuM6OkHxqXtE/1nUZZpihg29RtuIyfvk= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= diff --git a/hooks/hookexecution/enricher.go b/hooks/hookexecution/enricher.go index 7ca9f65f176..17a2eb9cc96 100644 --- a/hooks/hookexecution/enricher.go +++ b/hooks/hookexecution/enricher.go @@ -7,7 +7,7 @@ import ( "github.com/prebid/openrtb/v20/openrtb2" "github.com/prebid/prebid-server/v3/config" "github.com/prebid/prebid-server/v3/util/jsonutil" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" ) const ( diff --git a/openrtb_ext/bidders.go b/openrtb_ext/bidders.go index 10755dfd7fd..67cf8e7c15e 100644 --- a/openrtb_ext/bidders.go +++ b/openrtb_ext/bidders.go @@ -157,6 +157,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderLoyal, BidderLunaMedia, BidderMabidder, + BidderMadSense, BidderMadvertise, BidderMarsmedia, BidderMediafuse, @@ -171,6 +172,7 @@ var coreBidderNames []BidderName = []BidderName{ BidderMissena, BidderMobfoxpb, BidderMobileFuse, + BidderMobkoi, BidderMotorik, BidderNativo, BidderNextMillennium, @@ -511,6 +513,7 @@ const ( BidderLoyal BidderName = "loyal" BidderLunaMedia BidderName = "lunamedia" BidderMabidder BidderName = "mabidder" + BidderMadSense BidderName = "madsense" BidderMadvertise BidderName = "madvertise" BidderMarsmedia BidderName = "marsmedia" BidderMediafuse BidderName = "mediafuse" @@ -525,6 +528,7 @@ const ( BidderMissena BidderName = "missena" BidderMobfoxpb BidderName = "mobfoxpb" BidderMobileFuse BidderName = "mobilefuse" + BidderMobkoi BidderName = "mobkoi" BidderMotorik BidderName = "motorik" BidderNativo BidderName = "nativo" BidderNextMillennium BidderName = "nextmillennium" diff --git a/openrtb_ext/imp_appnexus.go b/openrtb_ext/imp_appnexus.go index 9e7a43495c8..bde37bdc9de 100644 --- a/openrtb_ext/imp_appnexus.go +++ b/openrtb_ext/imp_appnexus.go @@ -15,7 +15,7 @@ type ExtImpAppnexus struct { LegacyTrafficSourceCode string `json:"trafficSourceCode"` PlacementId jsonutil.StringInt `json:"placement_id"` InvCode string `json:"inv_code"` - Member string `json:"member"` + Member jsonutil.IntString `json:"member"` Keywords ExtImpAppnexusKeywords `json:"keywords"` TrafficSourceCode string `json:"traffic_source_code"` Reserve float64 `json:"reserve"` diff --git a/openrtb_ext/imp_madsense.go b/openrtb_ext/imp_madsense.go new file mode 100644 index 00000000000..a0d4c0a6df0 --- /dev/null +++ b/openrtb_ext/imp_madsense.go @@ -0,0 +1,5 @@ +package openrtb_ext + +type ExtImpMadSense struct { + CompanyId string `json:"company_id"` +} diff --git a/openrtb_ext/imp_mobkoi.go b/openrtb_ext/imp_mobkoi.go new file mode 100644 index 00000000000..ffb110e9eab --- /dev/null +++ b/openrtb_ext/imp_mobkoi.go @@ -0,0 +1,6 @@ +package openrtb_ext + +type ImpExtMobkoi struct { + PlacementID string `json:"placementId"` + AdServerBaseUrl string `json:"adServerBaseUrl"` +} diff --git a/openrtb_ext/imp_thetradedesk.go b/openrtb_ext/imp_thetradedesk.go index 89cca83f65e..bb2b628d773 100644 --- a/openrtb_ext/imp_thetradedesk.go +++ b/openrtb_ext/imp_thetradedesk.go @@ -1,8 +1,7 @@ package openrtb_ext -// ExtImpTheTradeDesk defines the contract for bidrequest.imp[i].ext -// PublisherId is mandatory parameters, others are optional parameters - +// ExtImpTheTradeDesk defines the contract for bidrequest.imp[i].ext.prebid.bidder.thetradedesk type ExtImpTheTradeDesk struct { - PublisherId string `json:"publisherId"` + PublisherId string `json:"publisherId"` + SupplySourceId string `json:"supplySourceId"` } diff --git a/openrtb_ext/imp_zeta_global_ssp.go b/openrtb_ext/imp_zeta_global_ssp.go new file mode 100644 index 00000000000..e721523da11 --- /dev/null +++ b/openrtb_ext/imp_zeta_global_ssp.go @@ -0,0 +1,5 @@ +package openrtb_ext + +type ImpExtZetaGlobalSsp struct { + Sid int `json:"sid"` +} diff --git a/openrtb_ext/preferredmediatype.go b/openrtb_ext/preferredmediatype.go new file mode 100644 index 00000000000..5fdfb740a06 --- /dev/null +++ b/openrtb_ext/preferredmediatype.go @@ -0,0 +1,3 @@ +package openrtb_ext + +type PreferredMediaType map[BidderName]BidType diff --git a/openrtb_ext/request.go b/openrtb_ext/request.go index 46cdb1a674a..a05133fc377 100644 --- a/openrtb_ext/request.go +++ b/openrtb_ext/request.go @@ -91,6 +91,8 @@ type ExtRequestPrebid struct { // - basic: excludes debugmessages and analytic_tags from output // any other value or an empty string disables trace output at all. Trace string `json:"trace,omitempty"` + + BidderControls map[BidderName]BidderControl `json:"biddercontrols,omitempty"` } type AdServerTarget struct { @@ -367,6 +369,10 @@ type ExtMultiBid struct { TargetBidderCodePrefix string `json:"targetbiddercodeprefix,omitempty"` } +type BidderControl struct { + PreferredMediaType BidType `json:"prefmtype"` +} + func (m ExtMultiBid) String() string { maxBid := "" if m.MaxBids != nil { diff --git a/router/router.go b/router/router.go index d412b5152e2..9e3d9fd4831 100644 --- a/router/router.go +++ b/router/router.go @@ -217,7 +217,7 @@ func New(cfg *config.Configuration, rateConvertor *currency.RateConverter) (r *R cacheClient := pbc.NewClient(cacheHttpClient, &cfg.CacheURL, &cfg.ExtCacheURL, r.MetricsEngine) - adapters, adaptersErrs := exchange.BuildAdapters(generalHttpClient, cfg, cfg.BidderInfos, r.MetricsEngine) + adapters, singleFormatAdapters, adaptersErrs := exchange.BuildAdapters(generalHttpClient, cfg, cfg.BidderInfos, r.MetricsEngine) if len(adaptersErrs) > 0 { errs := errortypes.NewAggregateError("Failed to initialize adapters", adaptersErrs) return nil, errs @@ -233,7 +233,7 @@ func New(cfg *config.Configuration, rateConvertor *currency.RateConverter) (r *R tmaxAdjustments := exchange.ProcessTMaxAdjustments(cfg.TmaxAdjustments) planBuilder := hooks.NewExecutionPlanBuilder(cfg.Hooks, repo) macroReplacer := macros.NewStringIndexBasedReplacer() - theExchange := exchange.NewExchange(adapters, cacheClient, cfg, requestValidator, syncersByBidder, r.MetricsEngine, cfg.BidderInfos, gdprPermsBuilder, rateConvertor, categoriesFetcher, adsCertSigner, macroReplacer, priceFloorFetcher) + theExchange := exchange.NewExchange(adapters, cacheClient, cfg, requestValidator, syncersByBidder, r.MetricsEngine, cfg.BidderInfos, gdprPermsBuilder, rateConvertor, categoriesFetcher, adsCertSigner, macroReplacer, priceFloorFetcher, singleFormatAdapters) var uuidGenerator uuidutil.UUIDRandomGenerator openrtbEndpoint, err := openrtb2.NewEndpoint(uuidGenerator, theExchange, requestValidator, fetcher, accounts, cfg, r.MetricsEngine, analyticsRunner, disabledBidders, defReqJSON, activeBidders, storedRespFetcher, planBuilder, tmaxAdjustments) if err != nil { diff --git a/server/ssl/ssl.go b/server/ssl/ssl.go index f206fb7beed..8b00b7d191b 100644 --- a/server/ssl/ssl.go +++ b/server/ssl/ssl.go @@ -116,6 +116,56 @@ RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw +CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw +FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S +Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 +MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL +DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS +QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH +sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK +Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu +SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC +MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy +v+c= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV +BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk +YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV +BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN +MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF +UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD +VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v +dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj +cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q +yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH +2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX +H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL +zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR +p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz +W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/ +SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn +LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3 +n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B +u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj +o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC +AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L +9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej +rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK +pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0 +vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq +OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ +/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9 +2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI ++PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2 +MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo +tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 @@ -149,31 +199,6 @@ LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU -MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs -IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 -MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h -bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v -dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt -H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 -uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX -mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX -a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN -E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 -WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD -VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 -Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU -cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx -IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN -AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH -YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 -6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC -Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX -c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a -mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL @@ -355,10 +380,55 @@ lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w +LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w +CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 +MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF +Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X +tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 +AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 +KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD +aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu +CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo +9H1/IISpQuQo +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM +MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx +MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 +MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD +QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z +4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv +Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ +kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs +GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln +nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh +3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD +0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy +geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 +ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB +c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI +pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS +4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs +o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ +qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw +xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM +rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 +AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR +0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY +o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 +dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE +oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h -cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy -MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1 +MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM @@ -371,23 +441,69 @@ Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF 6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh -OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD -VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD -VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp -cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv -ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl -AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF -661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 -am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 -ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 -PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS -3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k -SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF -3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM -ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g -StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz -Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB -jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc +tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd +IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j +b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC +AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw +ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m +iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF +Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ +hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P +Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE +EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV +1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t +CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR +5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw +f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9 +ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK +GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU +MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI +T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz +MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF +SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh +bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z +xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ +spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 +58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR +at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll +5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq +nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK +V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ +pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO +z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn +jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ +WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF +7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 +YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli +awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u ++2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 +X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN +SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo +P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI ++pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz +znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 +eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 +YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy +r/6zcCwupvI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw +CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ +VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy +MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ +TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS +b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B +IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ ++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK +sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA +94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B +43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ @@ -611,6 +727,50 @@ QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl NVOFBkpdn627G190 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw +CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu +bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ +BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s +eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK ++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2 +QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4 +hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm +ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG +BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw +PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy +dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9 +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0 +YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2 +1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT +vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed +aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0 +1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5 +r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5 +cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ +wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ +6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA +2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH +Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR +eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u +d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr +PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi +1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd +rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di +taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7 +lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj +yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn +Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy +yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n +wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6 +OV+KmalBWQewLK8= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ @@ -633,103 +793,55 @@ t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET -MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb -BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz -MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx -FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g -Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2 -fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl -LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV -WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF -TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb -5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc -CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri -wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ -wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG -m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4 -F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng -WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0 -2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF -AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/ -0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw -F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS -g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj -qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN -h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/ -ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V -btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj -Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ -8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW -gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw -PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz -cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 -MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz -IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ -ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR -VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL -kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd -EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas -H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 -HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud -DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 -QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu -Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ -AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 -yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR -FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA -ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB -kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 -l7+ijrRU ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa -MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy -dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a -iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt -6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP -0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f -6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE -EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN -1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc -h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT -mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV -4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO -WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud -DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd -Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq -hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh -66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7 -/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS -S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j -2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R -Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr -RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy -6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV -V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5 -g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl -++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x -CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs -dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat -93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x -Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P -AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj -FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG -SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch -p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal -U5ORGpOucGpnutee5WEaXw== +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw +CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw +JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT +EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 +WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT +LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX +BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE +KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm +Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 +EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J +UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn +nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM @@ -788,46 +900,127 @@ XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P DrW5viSP -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz -IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz -MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj -dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw -EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp -MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 -28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq -VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q -DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR -5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL -ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a -Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl -UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s -+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 -Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj -ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx -hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV -HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 -+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN -YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t -L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy -ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt -IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV -HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w -DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW -PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF -5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 -glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH -FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 -pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD -xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG -tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq -jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De -fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg -OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ -d0jQ +MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6 +MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu +MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV +BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw +MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg +U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ +n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q +p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq +NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF +8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3 +HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa +mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi +7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF +ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P +qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ +v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6 +Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1 +vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD +ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4 +WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo +zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR +5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ +GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf +5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq +0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D +P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM +qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP +0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf +E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMw +TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t +bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNa +Fw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv +cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDEw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLxeP0C +flfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJE +hRGnSjot6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggq +hkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg +2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uS +Um9poIyNStDuiw7LR47QjRE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMw +TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t +bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRa +Fw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv +cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDIw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/MMDAL +j2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmU +v4RDsNuESgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggq +hkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/n +ich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AV +mkzw5l4lIhVtwodZ0LKOag== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQEL +BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi +Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1 +NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t +U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt +MDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45FtnYSk +YZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslh +suitQDy6uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0al +DrJLpA6lfO741GIDuZNqihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3Oj +WiE260f6GBfZumbCk6SP/F2krfxQapWsvCQz0b2If4b19bJzKo98rwjyGpg/qYFl +P8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/cZip8UlF1y5mO6D1cv547 +KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTifBSeolz7p +UcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/ +kQO9lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JO +Hg9O5j9ZpSPcPYeoKFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkB +Ea801M/XrmLTBQe0MXXgDW1XT2mH+VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6U +CBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm45P3luG0wDQYJ +KoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6 +NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQ +nmhUQo8mUuJM3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+ +QgvfKNmwrZggvkN80V4aCRckjXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2v +trV0KnahP/t1MJ+UXjulYPPLXAziDslg+MkfFoom3ecnf+slpoq9uC02EJqxWE2a +aE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/WNyVntHKLr4W96ioD +j8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+o/E4 +Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0w +lREQKC6/oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHn +YfkUyq+Dj7+vsQpZXdxc1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVoc +icCMb3SgazNNtQEo/a2tiRc7ppqEvOuM6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQEL +BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi +Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2 +NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t +U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt +MDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3VrCLE +NQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0 +kyI9p+Kx7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1C +rWDaSWqVcN3SAOLMV2MCe5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxz +hkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2WWy09X6GDRl224yW4fKcZgBzqZUPckXk2 +LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rpM9kzXzehxfCrPfp4sOcs +n/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIfhs1w/tku +FT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5 +kQMreyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3 +wNemKfrb3vOTlycEVS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6v +wQcQeKwRoi9C8DfF8rhW3Q5iLc4tVn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs +5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7GxcJXvYXowDQYJ +KoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB +KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3 ++VGXu6TwYofF1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbyme +APnCKfWxkxlSaRosTKCL4BWaMS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3Nyq +pgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xdgSGn2rtO/+YHqP65DSdsu3BaVXoT +6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2OHG1QAk8mGEPej1WF +sQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+NmYWvt +PjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2d +lklyALKrdVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670 +v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17O +rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb @@ -855,26 +1048,40 @@ l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG -A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh -bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE -ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS -b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 -7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS -J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y -HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP -t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz -FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY -XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ -MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw -hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js -MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA -A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj -Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx -XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o -omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc -A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW -WL1WMRJOEcgh4LMRkWXbtKaIOM5V +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS +VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5 +NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG +A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB +BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS +zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0 +QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/ +VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g +PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf +Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l +dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 +c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO +PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW +wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV +dWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw +CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS +VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5 +NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG +A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC +/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD +wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3 +OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g +PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf +Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l +dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1 +c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO +PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA +y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb +gfM0agPnIjhQW+0ZT0MW -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF @@ -927,48 +1134,6 @@ xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ -MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT -DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow -PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD -Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O -rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq -OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b -xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw -7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD -aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG -SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 -ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr -AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz -R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 -JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo -Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc -MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj -IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB -IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE -RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl -U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 -IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU -ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC -QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr -rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S -NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc -QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH -txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP -BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC -AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp -tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa -IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl -6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ -xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU -Cm26OWMohpLzGITY+9HPBVZkVw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv @@ -1110,6 +1275,51 @@ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep +OkuE6N36B9K -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp +Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2 +MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ +bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS +7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp +0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS +B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49 +BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ +LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4 +DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN +MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT +HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN +NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs +IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+ +ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0 +2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp +wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM +pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD +nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po +sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx +Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd +Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX +KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe +XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL +tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv +TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN +AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H +PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF +O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ +REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik +AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv +/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+ +p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw +MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF +qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK +ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg @@ -1142,97 +1352,6 @@ r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV -BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC -aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV -BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 -Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz -MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ -BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp -em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY -B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH -D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF -Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo -q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D -k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH -fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut -dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM -ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 -zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX -U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 -Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 -XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF -Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR -HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY -GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c -77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 -+GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK -vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 -FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl -yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P -AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD -y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d -NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB -8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy -dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1 -YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3 -dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh -IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD -LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG -EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g -KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD -ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu -bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg -ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R -85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm -4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV -HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd -QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t -lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB -o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4 -opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo -dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW -ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN -AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y -/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k -SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy -Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS -Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl -nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 -MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 -czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG -CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy -MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl -ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS -b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy -euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO -bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw -WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d -MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE -1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD -VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ -zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB -BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF -BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV -v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG -E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u -uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW -iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v -GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 @@ -1328,6 +1447,42 @@ nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw +gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL +Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg +MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw +BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 +MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 +c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ +bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ +2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E +T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j +5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM +C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T +DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX +wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A +2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm +nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl +N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj +c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS +5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS +Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr +hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/ +B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI +AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw +H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+ +b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk +2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol +IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk +5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY +n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 @@ -1360,161 +1515,136 @@ T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL -MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj -KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 -MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw -NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV -BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL -So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal -tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG -CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT -qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz -rD6ogRLQy7rQkgu2npaqBA+K ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB -mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT -MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ -BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 -BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz -+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm -hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn -5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W -JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL -DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC -huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB -AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB -zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN -kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH -SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G -spki4cErx5z481+oghLrGREt ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy -c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 -IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV -VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 -cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT -QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh -F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v -c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w -mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd -VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX -teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ -f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe -Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ -nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY -MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX -IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn -ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z -uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN -Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja -QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW -koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 -ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt -DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm -bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy -c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD -VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 -c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 -WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG -FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq -XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL -se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb -KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd -IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 -y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt -hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc -QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 -Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV -HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ -KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ -L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr -Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo -ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY -T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz -GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m -1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV -OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH -6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX -QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk -MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH -bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ -FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F -uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX -kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs -ewv4n4Q= +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG +A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw +FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx +MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u +aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b +RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z +YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3 +QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw +yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+ +BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ +SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH +r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0 +4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me +dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw +q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2 +nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu +H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC +XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd +6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf ++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi +kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7 +wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB +TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C +MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn +4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I +aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy +qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo +27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w +Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw +TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl +qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH +szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 +Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk +MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 +wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p +aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN +VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb +C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy +h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 +7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J +ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef +MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ +Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT +6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ +0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm +2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb +bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt +nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY +6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu +MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k +RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg +f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV ++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo +dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW +Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa +G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq +gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID +AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H +vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC +B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u +NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg +yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev +HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6 +xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR +TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg +JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV +7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl +6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G +jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2 +4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7 +VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm +ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD +VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG +A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw +WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz +IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi +QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR +HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D +9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8 +p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD +VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw +MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g +UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT +BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx +uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV +HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/ ++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147 +bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk @@ -1552,28 +1682,6 @@ DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 @@ -1595,45 +1703,80 @@ Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH WD9f -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD -aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx -MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy -cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG -A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl -BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI -hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed -KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 -G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 -zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 -ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG -HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 -Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V -yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e -beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r -6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh -wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog -zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW -BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr -ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp -ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk -cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt -YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC -CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow -KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI -hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ -UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz -X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x -fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz -a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd -Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd -SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O -AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso -M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge -v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z -09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx +CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD +ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw +MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex +HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq +R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd +yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ +7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 ++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA +MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD +VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy +MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ +OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG +vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud +316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo +0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE +y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF +zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE ++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN +I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs +x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa +ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC +4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 +7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti +2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk +pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF +FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt +rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk +ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 +u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP +4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 +N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 +vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh @@ -1683,6 +1826,54 @@ LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI 4uJEvlz36hz1 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw +CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh +cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v +dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG +A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg +Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 +KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y +STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD +AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw +SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN +nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs +MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg +Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL +MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv +b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l +mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE +4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv +a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M +pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw +Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b +LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY +AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB +AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq +E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr +W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ +CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU +X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3 +f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja +H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP +JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P +zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt +jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0 +/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT +BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79 +aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW +xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU +63ZTGI0RmLo= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl @@ -1700,31 +1891,6 @@ lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix -RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 -dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p -YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw -NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK -EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl -cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl -c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB -BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz -dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ -fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns -bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD -75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP -FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV -HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp -5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu -b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA -A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p -6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 -TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 -dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys -Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI -l7WdmplNsDz4SgCbZN2fOUvRJ9e4 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT @@ -1760,24 +1926,69 @@ e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 vm9qp/UsQu0yrbYhnr68 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx -FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg -Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG -A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr -b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ -jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn -PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh -ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 -nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h -q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED -MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC -mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 -7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB -oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs -EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO -fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi -AmvZWg== +MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa +Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3 +YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw +qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv +Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6 +lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz +Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ +KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK +FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj +HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr +y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ +/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM +a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6 +fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG +SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi +7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc +SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza +ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc +XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg +iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho +L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF +Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr +kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+ +vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU +YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL +BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ +SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n +a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5 +NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT +CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u +Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO +dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI +VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV +9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY +2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY +vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt +bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb +x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+ +l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK +TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj +Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e +i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw +DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG +7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk +MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr +gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk +GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS +3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm +Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+ +l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c +JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP +L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa +LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG +mpv0 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw @@ -1811,6 +2022,20 @@ mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw +CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg +R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00 +MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT +ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW ++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9 +ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI +zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW +tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1 +/q4AaOeMSQ+2b1tbFfLn +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw @@ -1907,39 +2132,6 @@ naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQEL -BQAwRjELMAkGA1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNV -BAMMFkx1eFRydXN0IEdsb2JhbCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUw -MzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEWMBQGA1UECgwNTHV4VHJ1c3QgUy5B -LjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wmKb3F -ibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTem -hfY7RBi2xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1 -EMShduxq3sVs35a0VkBCwGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsn -Xpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4 -zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkmFRseTJIpgp7VkoGSQXAZ -96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niFwpN6cj5m -j5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4g -DEa/a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+ -8kPREd8vZS9kzl8UubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2j -X5t/Lax5Gw5CMZdjpPuKadUiDTSQMC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmH -hFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGByuB -KwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5Lmx1eHRydXN0 -Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT -+Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQEL -BQADggIBAGoZFO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9 -BzZAcg4atmpZ1gDlaCDdLnINH2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTO -jFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW7MM3LGVYvlcAGvI1+ut7MV3CwRI9 -loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIuZY+kt9J/Z93I055c -qqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWAVWe+ -2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/ -JEAdemrRTxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKre -zrnK+T+Tb/mjuuqlPpmt/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQf -LSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+ -x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31IiyBMz2TWuJdGsE7RKlY6 -oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G @@ -1964,6 +2156,87 @@ tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD +VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw +MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy +b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR +ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb +hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 +FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV +L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB +iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl +MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N +aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ +Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 +ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 +HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm +gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ +jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc +aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG +YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 +W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K +UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH ++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q +W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC +LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC +gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 +tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh +SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 +TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 +pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR +xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp +GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 +dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN +AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB +RA+GsCyRxj3qrg+E +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM +BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG +T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx +CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD +b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA +iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH +38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE +HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz +kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP +szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq +vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf +nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG +YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo +0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a +CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K +AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I +36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN +qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj +cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm ++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL +hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe +lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7 +p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8 +piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR +LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX +5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO +dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul +9XXeifdy +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl @@ -1988,53 +2261,6 @@ uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi -MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu -MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp -dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV -UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO -ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz -c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP -OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl -mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF -BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 -qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw -gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB -BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu -bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp -dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 -6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ -h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH -/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv -wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN -pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB -ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly -aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl -ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w -NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G -A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD -VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX -SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR -VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 -w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF -mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg -4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 -4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw -EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx -SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 -ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 -vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa -hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi -Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ -/L7fCg0= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i @@ -2057,116 +2283,19 @@ aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b -wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX -/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0 -77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP -uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx -p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx -Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2 -TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W -G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw -vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY -EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1 -2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw -DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E -PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf -gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS -FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0 -V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P -XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I -i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t -TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91 -09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky -Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ -AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj -1oxx ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA -MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w -ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw -MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU -T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh -/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e -CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6 -1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE -FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS -gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X -G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy -YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH -vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4 -t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/ -gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO -BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3 -5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w -DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz -Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0 -nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT -RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT -wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2 -t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa -TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2 -o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU -3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA -iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f -WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM -S1IK ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx -CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U -cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow -QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl -blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm -3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d -oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G -A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5 -DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK -BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q -j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx -4nxp5V2a+EEfOzmTk51V6s2N8fvB ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz -MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw -IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR -dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp -li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D -rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ -WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug -F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU -xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC -Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv -dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw -ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl -IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh -c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy -ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI -KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T -KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq -y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p -dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD -VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk -fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 -7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R -cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y -mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW -xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK -SnQ2+Q== +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL @@ -2433,6 +2562,52 @@ oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY Ic2wBlX7Jz9TkHCpBB5XJ7k= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT +U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 +MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh +dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm +acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN +SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME +GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW +uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp +15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN +b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO +MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD +DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX +DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw +b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP +L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY +t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins +S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 +PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO +L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 +R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w +dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS ++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS +d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG +AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f +gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z +NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt +hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM +QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf +R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ +DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW +P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy +lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq +bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w +AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q +r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji +Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU +98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw @@ -2454,6 +2629,52 @@ d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw +CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T +ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN +MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG +A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT +ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC +WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ +6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B +Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa +qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q +4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD +Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw +HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY +MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp +YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa +ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz +SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf +iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X +ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 +IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS +VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE +SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu ++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt +8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L +HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt +zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P +AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c +mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ +YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 +gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA +Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB +JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX +DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui +TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 +dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 +LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp +0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY +QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 @@ -2519,6 +2740,20 @@ iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT +AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD +VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx +NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT +HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5 +IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl +dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK +ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu +9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O +be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX @@ -2540,6 +2775,38 @@ t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNV +BAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScw +JQYDVQQDEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2 +MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UEAxMeU2VjdXJpdHkg +Q29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4r +CmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzA +lrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MG +TfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF7 +9+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK7 +8vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4 +g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3we +GVPKp7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst ++3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M +0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQ +T9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEAAaNCMEAw +HQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS +YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PA +FNr0Y/Dq9HHuTofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd +9XbXv8S2gVj/yP9kaWJ5rW4OH3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQI +UYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+ +OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZXSEIx2C/pHF7uNke +gr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml+LLf +iAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUV +nuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD +2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI// +1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8Laad +TdJ0MN1kURXbg4NR16/9M51NZg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 @@ -2560,122 +2827,6 @@ JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y -MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg -TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS -b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS -M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC -UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d -Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p -rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l -pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb -j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC -KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS -/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X -cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH -1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP -px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB -/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 -MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI -eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u -2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS -v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC -wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy -CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e -vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 -Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa -Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL -eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 -FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc -7uzXLg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX -DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 -qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp -uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU -Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE -pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp -5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M -UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN -GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy -5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv -6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK -eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 -B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ -BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov -L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV -HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG -SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS -CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen -5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 -IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK -gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL -+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL -vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm -bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk -N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC -Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z -ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX -DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP -cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW -IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX -xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy -KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR -9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az -5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 -6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 -Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP -bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt -BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt -XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd -INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD -U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp -LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 -Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp -gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh -/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw -0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A -fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq -4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR -1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ -QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM -94B7IWcnMFk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw @@ -2937,38 +3088,6 @@ aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ -MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj -YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow -PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp -Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB -AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR -IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q -gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy -yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts -F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 -jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx -ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC -VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK -YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH -EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN -Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud -DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE -MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK -UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ -TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf -qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK -ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE -JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 -hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 -EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm -nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX -udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz -ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe -LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl -pYYsfPQS ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD @@ -2999,136 +3118,245 @@ HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD -VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk -MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y -IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV -BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw -IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy -dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig -RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb -3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA -BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 -3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou -owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ -wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF -ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf -BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv -civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 -AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F -hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 -soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI -WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi -tJ/X5g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD -VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk -MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U -cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y -IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB -pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h -IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG -A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU -cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid -RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V -seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme -9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV -EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW -hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ -DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw -DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD -ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I -/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf -ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ -yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts -L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN -zl/HHk484IkzlQsPpTLWPFp5LBk= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV -BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw -IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy -dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig -Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk -MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg -Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD -VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy -dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK -AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ -QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq -1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp -2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK -DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape -az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF -3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 -oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM -g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 -mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh -8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd -BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U -nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw -DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX -dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ -MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL -/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX -CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa -ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW -2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 -N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 -Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB -As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp -5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu -1uwJ ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF -MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL -ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx -MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc -MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ -AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH -iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj -vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA -0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB -OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ -BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E -FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 -GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW -zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 -1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE -f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F -jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN -ZetX2fNXlrtIzYE= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE -BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn -aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg -QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg -SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0 -MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD -VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 -dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom -/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR -Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3 -4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z -5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0 -hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID -AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/ -BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX -SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l -VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq -URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf -peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF -Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW -+qtB4Uu2NQvAmxU= +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx +CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE +AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1 +NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ +MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq +AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9 +vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9 +lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD +n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT +7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o +6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC +TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6 +WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R +DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI +pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj +YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy +rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi +0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM +A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS +SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K +TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF +6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er +3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt +Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT +VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW +ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA +rBPuUBQemMc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM +BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp +ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe +Fw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUw +IwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtU +cnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNS +T1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqK +AtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1 +nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Ep +qq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXA +yB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMs +hH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gX +zhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAv +kV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msT +f9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jA +uPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQAB +o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/Ih +MBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E +BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4 +wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2 +XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1 +JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6j +ITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eV +VHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIx +xHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1on +AX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d +7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2Ntjj +gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV ++Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo +FGWsJwt0ivKH +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw +WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs +IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y +MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD +VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz +dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx +s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw +LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij +YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD +pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE +AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR +UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj +/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw +CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x +ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 +c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx +OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI +SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn +swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu +7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 +1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW +80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP +JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l +RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw +hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 +coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc +BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n +twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud +DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W +0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe +uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q +lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB +aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE +sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT +MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe +qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh +VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 +h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 +EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK +yeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN +FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w +DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw +CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh +DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB +BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ +j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF +1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G +A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 +AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC +MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu +Sw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL +BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg +Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv +b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG +EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u +IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ +n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd +2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF +VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ +GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF +li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU +r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 +eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb +MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg +jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB +7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW +5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE +ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z +xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu +QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 +FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH +22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP +xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn +dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 +Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b +nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ +CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH +u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj +d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF +eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx +MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV +BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog +D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS +sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop +O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk +sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi +c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj +VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz +KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ +TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G +sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs +1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD +fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN +l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ +VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 +c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp +4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s +t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj +2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO +vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C +xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx +cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM +fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH +bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x +CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds +b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr +b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 +kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm +VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R +VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc +C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj +tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY +D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv +j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl +NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 +iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP +O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV +ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj +L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl +1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU +b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV +PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj +y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb +EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg +DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI ++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy +YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX +UB+K+wb1whnw0A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL @@ -3181,129 +3409,6 @@ L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG jjxDah2nGN59PRbxYvnKkKj9 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp -U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg -SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln -biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm -GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve -fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ -aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj -aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW -kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC -4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga -FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB -vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W -ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 -IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y -IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh -bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF -9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH -H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H -LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN -/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT -rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw -WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs -exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 -sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ -seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz -4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ -BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR -lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 -7M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw -CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl -cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu -LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT -aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp -dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD -VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT -aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ -bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu -IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b -N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t -KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu -kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm -CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ -Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu -imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te -2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe -DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC -/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p -F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt -TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr -MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl -cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv -bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw -CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h -dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l -cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h -2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E -lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV -ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq -299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t -vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL -dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF -AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR -zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 -LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd -7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw -++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt -398znM/jra6O1I7mT1GvFpLgXPYHDw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY @@ -3349,6 +3454,52 @@ i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN 9u6wWk5JRFRYX0KD -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g +Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ +BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ +R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF +dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw +vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ +uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp +n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs +cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW +xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P +rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF +DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx +DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy +LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C +eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ +d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq +kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl +qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 +OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c +NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk +ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO +pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj +03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk +PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE +1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX +QRBdJ3NghVdJIgc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV +BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk +LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv +b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ +BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg +THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v +IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv +xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H +Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB +eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo +jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ ++efcMQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe @@ -3382,69 +3533,120 @@ W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D hNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp -IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi -BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw -MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig -YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v -dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ -BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 -papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K -DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 -KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox -XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB -rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV -BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa -Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl -LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u -MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm -gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 -YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf -b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 -9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S -zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk -OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV -HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA -2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW -oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c -KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM -m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu -MdRAGmI0Nj81Aa6sY6A= +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG +EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx +IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND +IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci +MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti +sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O +BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB +Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c +3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J +0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG +EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo +bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ +TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s +b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 +WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS +fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB +zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq +hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB +CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD ++JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG +A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg +SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v +dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ +BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ +HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH +3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH +GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c +xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 +aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq +TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 +/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 +kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG +YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT ++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo +WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD +VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU +ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH +MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO +MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv +Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz +f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO +8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq +d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM +tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt +Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB +o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x +PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM +wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d +GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH +6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby +RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw +RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY +BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz +MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u +LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0 +v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd +e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw +V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA +AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG +GJTO +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL +BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x +FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx +MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s +THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc +IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU +AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+ +GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9 +8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH +flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt +J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim +0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN +pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ +UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW +OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB +AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet +8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd +nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j +bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM +Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv +TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS +S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr +I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9 +b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB +UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P +Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven +sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s= -----END CERTIFICATE----- `) diff --git a/static/bidder-info/admaticde.yaml b/static/bidder-info/admaticde.yaml new file mode 100644 index 00000000000..562aa183695 --- /dev/null +++ b/static/bidder-info/admaticde.yaml @@ -0,0 +1 @@ +aliasOf: "admatic" \ No newline at end of file diff --git a/static/bidder-info/adnuntius.yaml b/static/bidder-info/adnuntius.yaml index 0e1d86dd286..beb7c5d6ef6 100644 --- a/static/bidder-info/adnuntius.yaml +++ b/static/bidder-info/adnuntius.yaml @@ -7,6 +7,8 @@ capabilities: app: mediaTypes: - banner + - native site: mediaTypes: - banner + - native diff --git a/static/bidder-info/adtg_org.yaml b/static/bidder-info/adtg_org.yaml new file mode 100644 index 00000000000..60b13764b94 --- /dev/null +++ b/static/bidder-info/adtg_org.yaml @@ -0,0 +1,2 @@ +endpoint: "http://ads-pbs.rtb.adtarget.org/openrtb/{{.PublisherID}}?host={{.Host}}" +aliasOf: "limelightDigital" diff --git a/static/bidder-info/aidem.yaml b/static/bidder-info/aidem.yaml index 70f63526879..5cf6aac80c1 100644 --- a/static/bidder-info/aidem.yaml +++ b/static/bidder-info/aidem.yaml @@ -7,12 +7,10 @@ capabilities: mediaTypes: - banner - video - - native site: mediaTypes: - banner - video - - native userSync: redirect: url: https://gum.aidemsrv.com/prebid_sync?gdpr={{.GDPR}}&consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}} diff --git a/static/bidder-info/algorix.yaml b/static/bidder-info/algorix.yaml index dc5f80a5ebd..f80fa26e981 100644 --- a/static/bidder-info/algorix.yaml +++ b/static/bidder-info/algorix.yaml @@ -8,3 +8,8 @@ capabilities: - banner - video - native + site: + mediaTypes: + - banner + - video + - native diff --git a/static/bidder-info/criteo.yaml b/static/bidder-info/criteo.yaml index 0695f0cc134..908bfd4aeb9 100644 --- a/static/bidder-info/criteo.yaml +++ b/static/bidder-info/criteo.yaml @@ -2,6 +2,10 @@ endpoint: "https://ssp-bidder.criteo.com/openrtb/pbs/auction/request?profile=230 maintainer: email: "prebid@criteo.com" gvlVendorID: 91 +openrtb: + version: 2.6 + gpp-supported: true + multiformat-supported: true capabilities: app: mediaTypes: diff --git a/static/bidder-info/iionads.yaml b/static/bidder-info/iionads.yaml index 1dc154a358d..b782cc96116 100644 --- a/static/bidder-info/iionads.yaml +++ b/static/bidder-info/iionads.yaml @@ -1,2 +1,3 @@ endpoint: "http://ads-pbs.iionads.com/openrtb/{{.PublisherID}}?host={{.Host}}" -aliasOf: "limelightDigital" \ No newline at end of file +aliasOf: "limelightDigital" +gvlVendorID: 1358 diff --git a/static/bidder-info/improvedigital.yaml b/static/bidder-info/improvedigital.yaml index 4cd30d7c6b2..cb5ea798074 100644 --- a/static/bidder-info/improvedigital.yaml +++ b/static/bidder-info/improvedigital.yaml @@ -16,6 +16,9 @@ capabilities: - audio - native userSync: + iframe: + url: "https://ad.360yield.com/user_sync?rt=html&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&r={{.RedirectURL}}" + userMacro: "{PUB_USER_ID}" redirect: url: "https://ad.360yield.com/server_match?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&r={{.RedirectURL}}" userMacro: "{PUB_USER_ID}" diff --git a/static/bidder-info/inmobi.yaml b/static/bidder-info/inmobi.yaml index 3f0c9b9b480..2ae242cec60 100644 --- a/static/bidder-info/inmobi.yaml +++ b/static/bidder-info/inmobi.yaml @@ -17,4 +17,6 @@ userSync: iframe: url: "https://sync.inmobi.com/prebid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redirect={{.RedirectURL}}" userMacro: "{ID5UID}" - + redirect: + url: "https://sync.inmobi.com/prebid?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redirect={{.RedirectURL}}" + userMacro: "{ID5UID}" diff --git a/static/bidder-info/kobler.yaml b/static/bidder-info/kobler.yaml index 8429aaa4bb2..8a090f8e342 100644 --- a/static/bidder-info/kobler.yaml +++ b/static/bidder-info/kobler.yaml @@ -10,3 +10,6 @@ capabilities: site: mediaTypes: - banner + app: + mediaTypes: + - banner diff --git a/static/bidder-info/madsense.yaml b/static/bidder-info/madsense.yaml new file mode 100644 index 00000000000..4105c65fe98 --- /dev/null +++ b/static/bidder-info/madsense.yaml @@ -0,0 +1,12 @@ +endpoint: "https://ads.madsense.io/pbs" +maintainer: + email: "prebid@madsense.io" +capabilities: + app: + mediaTypes: + - banner + - video + site: + mediaTypes: + - banner + - video \ No newline at end of file diff --git a/static/bidder-info/mobkoi.yaml b/static/bidder-info/mobkoi.yaml new file mode 100644 index 00000000000..fcb17c3ba6f --- /dev/null +++ b/static/bidder-info/mobkoi.yaml @@ -0,0 +1,10 @@ +endpoint: "https://pbs.maximus.mobkoi.com/bid" +maintainer: + email: platformteam@mobkoi.com +gvlVendorID: 898 +openrtb: + version: 2.6 +capabilities: + site: + mediaTypes: + - banner diff --git a/static/bidder-info/monetixads.yaml b/static/bidder-info/monetixads.yaml new file mode 100644 index 00000000000..95beda701f0 --- /dev/null +++ b/static/bidder-info/monetixads.yaml @@ -0,0 +1,3 @@ +aliasOf: "admatic" +maintainer: + email: "team@monetixads.com" \ No newline at end of file diff --git a/static/bidder-info/nextmillennium.yaml b/static/bidder-info/nextmillennium.yaml index 11182ac271c..42b3bc082e5 100644 --- a/static/bidder-info/nextmillennium.yaml +++ b/static/bidder-info/nextmillennium.yaml @@ -1,4 +1,5 @@ endpoint: "https://pbs.nextmillmedia.com/openrtb2/auction" +endpointCompression: GZIP maintainer: email: "accountmanagers@nextmillennium.io" gvlVendorID: 1060 diff --git a/static/bidder-info/orangeclickmedia.yaml b/static/bidder-info/orangeclickmedia.yaml new file mode 100644 index 00000000000..841c4cd49e6 --- /dev/null +++ b/static/bidder-info/orangeclickmedia.yaml @@ -0,0 +1,2 @@ +endpoint: "http://ads-pbs.scotty.orangeclickmedia.com/openrtb/{{.PublisherID}}?host={{.Host}}" +aliasOf: "limelightDigital" diff --git a/static/bidder-info/pixad.yaml b/static/bidder-info/pixad.yaml new file mode 100644 index 00000000000..d08230bfbc3 --- /dev/null +++ b/static/bidder-info/pixad.yaml @@ -0,0 +1,3 @@ +aliasOf: "admatic" +maintainer: + email: "prebid@pixad.com.tr" \ No newline at end of file diff --git a/static/bidder-info/smaato.yaml b/static/bidder-info/smaato.yaml index 2b1b5c3fe17..071190ce79d 100644 --- a/static/bidder-info/smaato.yaml +++ b/static/bidder-info/smaato.yaml @@ -20,4 +20,7 @@ userSync: redirect: url: "https://s.ad.smaato.net/c/?adExInit=p&redir={{.RedirectURL}}&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}" userMacro: "$UID" + iframe: + url: "https://s.ad.smaato.net/i/?adExInit=p&redir={{.RedirectURL}}&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}" + userMacro: "$UID" diff --git a/static/bidder-info/smilewanted.yaml b/static/bidder-info/smilewanted.yaml index 44aff8a055a..e0648d417f9 100644 --- a/static/bidder-info/smilewanted.yaml +++ b/static/bidder-info/smilewanted.yaml @@ -1,4 +1,4 @@ -endpoint: "http://prebid-server.smilewanted.com" +endpoint: "https://prebid-server.smilewanted.com" maintainer: email: "tech@smilewanted.com" gvlVendorID: 639 @@ -14,4 +14,4 @@ capabilities: userSync: redirect: url: "https://csync.smilewanted.com/getuid?source=prebid-server&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}" - userMacro: "$UID" \ No newline at end of file + userMacro: "$UID" diff --git a/static/bidder-info/trustedstack.yaml b/static/bidder-info/trustedstack.yaml index ffa48d261d4..09bb3313327 100644 --- a/static/bidder-info/trustedstack.yaml +++ b/static/bidder-info/trustedstack.yaml @@ -19,6 +19,9 @@ capabilities: - video - native userSync: + iframe: + url: https://hb.trustedstack.com/checksync.php?cid=TS2Q14L8J&cs=87&type=mpbc&cv=37&vsSync=1&uspstring={{.USPrivacy}}&gdpr={{.GDPR}}&gdprstring={{.GDPRConsent}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}}&redirect={{.RedirectURL}} + userMacro: "" redirect: url: https://hb.trustedstack.com/cksync?cs=1&type=pbs&ovsid=setstatuscode&bidder=trustedstack&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&redirect={{.RedirectURL}}&gpp={{.GPP}}&gpp_sid={{.GPPSID}} userMacro: "" \ No newline at end of file diff --git a/static/bidder-info/velonium.yaml b/static/bidder-info/velonium.yaml new file mode 100644 index 00000000000..0a90a983267 --- /dev/null +++ b/static/bidder-info/velonium.yaml @@ -0,0 +1,2 @@ +endpoint: "http://ads-pbs.adxvel.com/openrtb/{{.PublisherID}}?host={{.Host}}" +aliasOf: "limelightDigital" diff --git a/static/bidder-info/yobee.yaml b/static/bidder-info/yobee.yaml new file mode 100644 index 00000000000..28ce00e79d0 --- /dev/null +++ b/static/bidder-info/yobee.yaml @@ -0,0 +1,3 @@ +aliasOf: "admatic" +maintainer: + email: "adops@yobee.it" \ No newline at end of file diff --git a/static/bidder-info/zeta_global_ssp.yaml b/static/bidder-info/zeta_global_ssp.yaml index 479f024c1b7..f4f50d94b7d 100644 --- a/static/bidder-info/zeta_global_ssp.yaml +++ b/static/bidder-info/zeta_global_ssp.yaml @@ -1,5 +1,8 @@ -endpoint: https://ssp.disqus.com/bid/prebid-server?sid=GET_SID_FROM_ZETA +disabled: true +endpoint: https://ssp.disqus.com/bid/prebid-server?sid={{.AccountID}} endpointCompression: gzip +geoscope: + - global maintainer: email: DL-Zeta-SSP@zetaglobal.com gvlVendorID: 833 @@ -9,12 +12,14 @@ capabilities: mediaTypes: - banner - video + - audio site: mediaTypes: - banner - video + - audio userSync: redirect: - url: https://ssp.disqus.com/redirectuser?sid=GET_SID_FROM_ZETA&gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}} + url: https://ssp.disqus.com/redirectuser?gdpr={{.GDPR}}&gdpr_consent={{.GDPRConsent}}&us_privacy={{.USPrivacy}}&r={{.RedirectURL}} userMacro: 'BUYERUID' diff --git a/static/bidder-params/aidem.json b/static/bidder-params/aidem.json index 221e5ff7a92..0483dc4da25 100644 --- a/static/bidder-params/aidem.json +++ b/static/bidder-params/aidem.json @@ -17,7 +17,7 @@ "placementId": { "type": "string", "minLength": 1, - "description": "Unique publisher ttag ID" + "description": "Unique publisher tag ID" }, "rateLimit": { "type": "number", @@ -25,5 +25,8 @@ "maximum": 1 } }, - "required": ["siteId", "publisherId"] + "required": [ + "siteId", + "publisherId" + ] } \ No newline at end of file diff --git a/static/bidder-params/appnexus.json b/static/bidder-params/appnexus.json index 6a9a5d7d45d..37909b12066 100644 --- a/static/bidder-params/appnexus.json +++ b/static/bidder-params/appnexus.json @@ -22,7 +22,7 @@ "description": "Deprecated, use inv_code instead." }, "member": { - "type": "string", + "type": ["integer", "string"], "description": "An ID which identifies the member selling the impression." }, "keywords": { diff --git a/static/bidder-params/madsense.json b/static/bidder-params/madsense.json new file mode 100644 index 00000000000..54410fd2aee --- /dev/null +++ b/static/bidder-params/madsense.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "madSense Adapter Params", + "description": "A schema which validates params accepted by the madSense adapter", + "type": "object", + "properties": { + "company_id": { + "type": "string", + "description": "An id used to identify madSense company", + "minLength": 1 + } + }, + "required": ["company_id"] +} diff --git a/static/bidder-params/mobkoi.json b/static/bidder-params/mobkoi.json new file mode 100644 index 00000000000..8286229b035 --- /dev/null +++ b/static/bidder-params/mobkoi.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Mobkoi Adapter Params", + "description": "A schema which validates params accepted by the Mobkoi adapter", + "type": "object", + "properties": { + "placementId": { + "type": "string", + "description": "Placement ID" + }, + "adServerBaseUrl": { + "type": "string", + "description": "Mobkoi's ad server url", + "pattern": "^https?://[^.]+\\.mobkoi\\.com$" + } + } +} diff --git a/static/bidder-params/thetradedesk.json b/static/bidder-params/thetradedesk.json index 5a85cf2f516..63dae6d9785 100644 --- a/static/bidder-params/thetradedesk.json +++ b/static/bidder-params/thetradedesk.json @@ -6,7 +6,13 @@ "properties": { "publisherId": { "type": "string", + "minLength": 1, "description": "An ID which identifies the publisher" + }, + "supplySourceId": { + "type":"string", + "minLength": 1, + "description": "An ID provided by TheTradeDesk used to determine which endpoint to use" } }, "required": ["publisherId"] diff --git a/static/bidder-params/zeta_global_ssp.json b/static/bidder-params/zeta_global_ssp.json index acfaa9c1988..8a6d1d0a060 100644 --- a/static/bidder-params/zeta_global_ssp.json +++ b/static/bidder-params/zeta_global_ssp.json @@ -4,5 +4,10 @@ "description": "A schema which validates params accepted by the Zeta Global SSP adapter", "type": "object", - "properties": {} + "properties": { + "sid": { + "type": "integer", + "description": "An ID which identifies the publisher" + } + } } diff --git a/stored_requests/backends/file_fetcher/fetcher.go b/stored_requests/backends/file_fetcher/fetcher.go index 1c51a353fb8..6bb8bc1447b 100644 --- a/stored_requests/backends/file_fetcher/fetcher.go +++ b/stored_requests/backends/file_fetcher/fetcher.go @@ -10,7 +10,7 @@ import ( "github.com/prebid/prebid-server/v3/stored_requests" "github.com/prebid/prebid-server/v3/util/jsonutil" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" ) // NewFileFetcher _immediately_ loads stored request data from local files. @@ -60,6 +60,9 @@ func (fetcher *eagerFetcher) FetchAccount(ctx context.Context, accountDefaultsJS }} } + if accountDefaultsJSON == nil { + return accountJSON, nil + } completeJSON, err := jsonpatch.MergePatch(accountDefaultsJSON, accountJSON) if err != nil { return nil, []error{err} diff --git a/stored_requests/backends/file_fetcher/fetcher_test.go b/stored_requests/backends/file_fetcher/fetcher_test.go index 80e45bb9445..735045dd9fe 100644 --- a/stored_requests/backends/file_fetcher/fetcher_test.go +++ b/stored_requests/backends/file_fetcher/fetcher_test.go @@ -83,6 +83,10 @@ func TestAccountFetcher(t *testing.T) { assertErrorCount(t, 0, errs) assert.JSONEq(t, `{"disabled":false, "events_enabled":true, "id":"valid" }`, string(account)) + account, errs = fetcher.FetchAccount(context.Background(), nil, "valid") + assertErrorCount(t, 0, errs) + assert.JSONEq(t, `{"disabled":false, "id":"valid" }`, string(account)) + _, errs = fetcher.FetchAccount(context.Background(), json.RawMessage(`{"events_enabled":true}`), "nonexistent") assertErrorCount(t, 1, errs) assert.Error(t, errs[0]) diff --git a/stored_requests/backends/http_fetcher/fetcher.go b/stored_requests/backends/http_fetcher/fetcher.go index dc4dd03a1fe..7f765b99327 100644 --- a/stored_requests/backends/http_fetcher/fetcher.go +++ b/stored_requests/backends/http_fetcher/fetcher.go @@ -11,7 +11,7 @@ import ( "github.com/prebid/prebid-server/v3/stored_requests" "github.com/prebid/prebid-server/v3/util/jsonutil" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" "github.com/golang/glog" "golang.org/x/net/context/ctxhttp" @@ -164,6 +164,9 @@ func (fetcher *HttpFetcher) FetchAccount(ctx context.Context, accountDefaultsJSO DataType: "Account", }} } + if accountDefaultsJSON == nil { + return accountJSON, nil + } completeJSON, err := jsonpatch.MergePatch(accountDefaultsJSON, accountJSON) if err != nil { return nil, []error{err} diff --git a/util/jsonutil/intstring.go b/util/jsonutil/intstring.go new file mode 100644 index 00000000000..09c91577cbe --- /dev/null +++ b/util/jsonutil/intstring.go @@ -0,0 +1,19 @@ +package jsonutil + +import ( + "errors" + + "github.com/tidwall/gjson" +) + +type IntString string + +func (st *IntString) UnmarshalJSON(b []byte) error { + res := gjson.ParseBytes(b) + if res.Type != gjson.Number && res.Type != gjson.String { + return errors.New("invalid type") + } + + *st = IntString(res.String()) + return nil +} diff --git a/util/jsonutil/intstring_test.go b/util/jsonutil/intstring_test.go new file mode 100644 index 00000000000..f8131701e72 --- /dev/null +++ b/util/jsonutil/intstring_test.go @@ -0,0 +1,58 @@ +package jsonutil + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIntStringUnmarshalJSON(t *testing.T) { + tests := []struct { + name string + jsonData json.RawMessage + expectError bool + want string + }{ + { + name: "null", + jsonData: []byte(`{"item_id": null}`), + want: "", + expectError: true, + }, + { + name: "string", + jsonData: []byte(`{"item_id": "30"}`), + want: "30", + }, + { + name: "int", + jsonData: []byte(`{"item_id": 30}`), + want: "30", + }, + { + name: "error", + jsonData: []byte(`{"item_id": []`), + want: "", + expectError: true, + }, + } + + type Item struct { + ItemId IntString `json:"item_id"` + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + var item Item + err := UnmarshalValid(test.jsonData, &item) + assert.Equal(t, string(test.want), string(item.ItemId)) + + if test.expectError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/util/jsonutil/merge.go b/util/jsonutil/merge.go index 2b7edc6ee25..6dff8afca64 100644 --- a/util/jsonutil/merge.go +++ b/util/jsonutil/merge.go @@ -8,7 +8,7 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/modern-go/reflect2" - jsonpatch "gopkg.in/evanphx/json-patch.v4" + jsonpatch "gopkg.in/evanphx/json-patch.v5" "github.com/prebid/prebid-server/v3/errortypes" )