Fix library exposure

This commit is contained in:
Thomas LAY
2020-04-03 17:13:48 +02:00
parent dfb30cea54
commit a95d955c6a
8 changed files with 219 additions and 219 deletions

16
bits.go
View File

@@ -9,11 +9,11 @@ var (
bytePows = []byte{128, 64, 32, 16, 8, 4, 2, 1}
)
func NewBits(bytes []byte) *Bits {
func newBits(bytes []byte) *Bits {
return &Bits{bytes: bytes, position: 0}
}
func (b *Bits) ReadBool() bool {
func (b *Bits) readBool() bool {
byteIndex := b.position / 8
bitIndex := b.position % 8
b.position++
@@ -21,7 +21,7 @@ func (b *Bits) ReadBool() bool {
return (b.bytes[byteIndex] & bytePows[bitIndex]) != 0
}
func (b *Bits) WriteBool(v bool) {
func (b *Bits) writeBool(v bool) {
byteIndex := b.position / 8
shift := (byteIndex+1)*8 - b.position - 1
b.position++
@@ -33,10 +33,10 @@ func (b *Bits) WriteBool(v bool) {
}
}
func (b *Bits) ReadInt(n uint) int {
func (b *Bits) readInt(n uint) int {
v := 0
for i, shift := uint(0), n-1; i < n; i++ {
if b.ReadBool() {
if b.readBool() {
v += 1 << uint(shift)
}
shift--
@@ -45,11 +45,11 @@ func (b *Bits) ReadInt(n uint) int {
return v
}
func (b *Bits) WriteInt(v int, n uint) {
b.WriteNumber(int64(v), n)
func (b *Bits) writeInt(v int, n uint) {
b.writeNumber(int64(v), n)
}
func (b *Bits) WriteNumber(v int64, n uint) {
func (b *Bits) writeNumber(v int64, n uint) {
startOffset := int(b.position)
for i := int(n) - 1; i >= 0; i-- {
index := startOffset + i

104
decode.go
View File

@@ -12,8 +12,8 @@ func DecodeSegmentType(s string) int {
return 0
}
var e = NewTCEncoder(b)
return e.ReadInt(3)
var e = newTCEncoder(b)
return e.readInt(3)
}
func Decode(s string) (t *TCData, err error) {
@@ -62,46 +62,46 @@ func DecodeCoreString(s string) (c *CoreString, err error) {
return nil, err
}
var e = NewTCEncoder(b)
var e = newTCEncoder(b)
c = &CoreString{}
c.Version = e.ReadInt(6)
c.Created = e.ReadTime()
c.LastUpdated = e.ReadTime()
c.CmpId = e.ReadInt(12)
c.CmpVersion = e.ReadInt(12)
c.ConsentScreen = e.ReadInt(6)
c.ConsentLanguage = e.ReadIsoCode()
c.VendorListVersion = e.ReadInt(12)
c.TcfPolicyVersion = e.ReadInt(6)
c.IsServiceSpecific = e.ReadBool()
c.UseNonStandardStacks = e.ReadBool()
c.SpecialFeatureOptIns = e.ReadBitField(12)
c.PurposesConsent = e.ReadBitField(24)
c.PurposesLITransparency = e.ReadBitField(24)
c.PurposeOneTreatment = e.ReadBool()
c.PublisherCC = e.ReadIsoCode()
c.Version = e.readInt(6)
c.Created = e.readTime()
c.LastUpdated = e.readTime()
c.CmpId = e.readInt(12)
c.CmpVersion = e.readInt(12)
c.ConsentScreen = e.readInt(6)
c.ConsentLanguage = e.readIsoCode()
c.VendorListVersion = e.readInt(12)
c.TcfPolicyVersion = e.readInt(6)
c.IsServiceSpecific = e.readBool()
c.UseNonStandardStacks = e.readBool()
c.SpecialFeatureOptIns = e.readBitField(12)
c.PurposesConsent = e.readBitField(24)
c.PurposesLITransparency = e.readBitField(24)
c.PurposeOneTreatment = e.readBool()
c.PublisherCC = e.readIsoCode()
c.MaxVendorId = e.ReadInt(16)
c.IsRangeEncoding = e.ReadBool()
c.MaxVendorId = e.readInt(16)
c.IsRangeEncoding = e.readBool()
if c.IsRangeEncoding {
c.NumEntries = e.ReadInt(12)
c.RangeEntries = e.ReadRangeEntries(uint(c.NumEntries))
c.NumEntries = e.readInt(12)
c.RangeEntries = e.readRangeEntries(uint(c.NumEntries))
} else {
c.VendorsConsent = e.ReadBitField(uint(c.MaxVendorId))
c.VendorsConsent = e.readBitField(uint(c.MaxVendorId))
}
c.MaxVendorIdLI = e.ReadInt(16)
c.IsRangeEncodingLI = e.ReadBool()
c.MaxVendorIdLI = e.readInt(16)
c.IsRangeEncodingLI = e.readBool()
if c.IsRangeEncodingLI {
c.NumEntriesLI = e.ReadInt(12)
c.RangeEntriesLI = e.ReadRangeEntries(uint(c.NumEntriesLI))
c.NumEntriesLI = e.readInt(12)
c.RangeEntriesLI = e.readRangeEntries(uint(c.NumEntriesLI))
} else {
c.VendorsLITransparency = e.ReadBitField(uint(c.MaxVendorIdLI))
c.VendorsLITransparency = e.readBitField(uint(c.MaxVendorIdLI))
}
c.NumPubRestrictions = e.ReadInt(12)
c.PubRestrictions = e.ReadPubRestrictions(uint(c.NumPubRestrictions))
c.NumPubRestrictions = e.readInt(12)
c.PubRestrictions = e.readPubRestrictions(uint(c.NumPubRestrictions))
return c, nil
}
@@ -118,17 +118,17 @@ func DecodeDisclosedVendors(s string) (d *DisclosedVendors, err error) {
return nil, err
}
var e = NewTCEncoder(b)
var e = newTCEncoder(b)
d = &DisclosedVendors{}
d.SegmentType = e.ReadInt(3)
d.MaxVendorId = e.ReadInt(16)
d.IsRangeEncoding = e.ReadBool()
d.SegmentType = e.readInt(3)
d.MaxVendorId = e.readInt(16)
d.IsRangeEncoding = e.readBool()
if d.IsRangeEncoding {
d.NumEntries = e.ReadInt(12)
d.RangeEntries = e.ReadRangeEntries(uint(d.NumEntries))
d.NumEntries = e.readInt(12)
d.RangeEntries = e.readRangeEntries(uint(d.NumEntries))
} else {
d.DisclosedVendors = e.ReadBitField(uint(d.MaxVendorId))
d.DisclosedVendors = e.readBitField(uint(d.MaxVendorId))
}
if d.SegmentType != 1 {
@@ -151,17 +151,17 @@ func DecodeAllowedVendors(s string) (a *AllowedVendors, err error) {
return nil, err
}
var e = NewTCEncoder(b)
var e = newTCEncoder(b)
a = &AllowedVendors{}
a.SegmentType = e.ReadInt(3)
a.MaxVendorId = e.ReadInt(16)
a.IsRangeEncoding = e.ReadBool()
a.SegmentType = e.readInt(3)
a.MaxVendorId = e.readInt(16)
a.IsRangeEncoding = e.readBool()
if a.IsRangeEncoding {
a.NumEntries = e.ReadInt(12)
a.RangeEntries = e.ReadRangeEntries(uint(a.NumEntries))
a.NumEntries = e.readInt(12)
a.RangeEntries = e.readRangeEntries(uint(a.NumEntries))
} else {
a.AllowedVendors = e.ReadBitField(uint(a.MaxVendorId))
a.AllowedVendors = e.readBitField(uint(a.MaxVendorId))
}
if a.SegmentType != 2 {
@@ -184,15 +184,15 @@ func DecodePubllisherTC(s string) (p *PublisherTC, err error) {
return nil, err
}
var e = NewTCEncoder(b)
var e = newTCEncoder(b)
p = &PublisherTC{}
p.SegmentType = e.ReadInt(3)
p.PubPurposesConsent = e.ReadBitField(24)
p.PubPurposesLITransparency = e.ReadBitField(24)
p.NumCustomPurposes = e.ReadInt(6)
p.CustomPurposesConsent = e.ReadBitField(uint(p.NumCustomPurposes))
p.CustomPurposesLITransparency = e.ReadBitField(uint(p.NumCustomPurposes))
p.SegmentType = e.readInt(3)
p.PubPurposesConsent = e.readBitField(24)
p.PubPurposesLITransparency = e.readBitField(24)
p.NumCustomPurposes = e.readInt(6)
p.CustomPurposesConsent = e.readBitField(uint(p.NumCustomPurposes))
p.CustomPurposesLITransparency = e.readBitField(uint(p.NumCustomPurposes))
if p.SegmentType != 3 {
err = fmt.Errorf("allowed vendors segment type must be 3")

View File

@@ -1,105 +0,0 @@
package iabtcf
import (
"time"
)
const (
decisecondsPerSecond = 10
nanosecondsPerDecisecond = int64(time.Millisecond * 100)
)
type TCEncoder struct {
*Bits
}
func NewTCEncoder(src []byte) *TCEncoder {
return &TCEncoder{NewBits(src)}
}
func (r *TCEncoder) ReadTime() time.Time {
var ds = int64(r.ReadInt(36))
return time.Unix(ds/decisecondsPerSecond, (ds%decisecondsPerSecond)*nanosecondsPerDecisecond).UTC()
}
func (r *TCEncoder) WriteTime(v time.Time) {
r.WriteNumber(v.UnixNano()/nanosecondsPerDecisecond, 36)
}
func (r *TCEncoder) ReadIsoCode() string {
var buf = make([]byte, 0, 2)
for i := uint(0); i < 2; i++ {
buf = append(buf, byte(r.ReadInt(6))+'A')
}
return string(buf)
}
func (r *TCEncoder) WriteIsoCode(v string) {
for _, char := range v {
r.WriteInt(int(byte(char)-'A'), 6)
}
}
func (r *TCEncoder) ReadBitField(n uint) map[int]bool {
var m = make(map[int]bool)
for i := uint(0); i < n; i++ {
if r.ReadBool() {
m[int(i)+1] = true
}
}
return m
}
func (r *TCEncoder) WriteRangeEntries(entries []*RangeEntry) {
for _, entry := range entries {
if entry.EndVendorID > entry.StartVendorID {
r.WriteBool(true)
r.WriteInt(entry.StartVendorID, 16)
r.WriteInt(entry.EndVendorID, 16)
} else {
r.WriteBool(false)
r.WriteInt(entry.StartVendorID, 16)
}
}
}
func (r *TCEncoder) ReadRangeEntries(n uint) []*RangeEntry {
var ret = make([]*RangeEntry, 0, n)
for i := uint(0); i < n; i++ {
var isRange = r.ReadBool()
var start, end int
start = r.ReadInt(16)
if isRange {
end = r.ReadInt(16)
} else {
end = start
}
ret = append(ret, &RangeEntry{StartVendorID: start, EndVendorID: end})
}
return ret
}
func (r *TCEncoder) WritePubRestrictions(entries []*PubRestriction) {
for _, entry := range entries {
r.WriteInt(entry.PurposeId, 6)
r.WriteInt(entry.RestrictionType, 2)
r.WriteInt(len(entry.RangeEntries), 12)
r.WriteRangeEntries(entry.RangeEntries)
}
}
func (r *TCEncoder) ReadPubRestrictions(n uint) []*PubRestriction {
var ret = make([]*PubRestriction, 0, n)
for i := uint(0); i < n; i++ {
var purposeId = r.ReadInt(6)
var restrictionType = r.ReadInt(2)
var numEntries = r.ReadInt(12)
var rangeEntries = r.ReadRangeEntries(uint(numEntries))
ret = append(ret, &PubRestriction{PurposeId: purposeId,
RestrictionType: restrictionType,
NumEntries: numEntries,
RangeEntries: rangeEntries,
})
}
return ret
}

View File

@@ -44,20 +44,20 @@ func (a *AllowedVendors) Encode() string {
bitSize += a.MaxVendorId
}
var e = NewTCEncoder(make([]byte, bitSize/8))
var e = newTCEncoder(make([]byte, bitSize/8))
if bitSize%8 != 0 {
e = NewTCEncoder(make([]byte, bitSize/8+1))
e = newTCEncoder(make([]byte, bitSize/8+1))
}
e.WriteInt(a.SegmentType, 3)
e.WriteInt(a.MaxVendorId, 16)
e.WriteBool(a.IsRangeEncoding)
e.writeInt(a.SegmentType, 3)
e.writeInt(a.MaxVendorId, 16)
e.writeBool(a.IsRangeEncoding)
if a.IsRangeEncoding {
e.WriteInt(len(a.RangeEntries), 12)
e.WriteRangeEntries(a.RangeEntries)
e.writeInt(len(a.RangeEntries), 12)
e.writeRangeEntries(a.RangeEntries)
} else {
for i := 0; i < a.MaxVendorId; i++ {
e.WriteBool(a.IsVendorAllowed(i + 1))
e.writeBool(a.IsVendorAllowed(i + 1))
}
}

View File

@@ -133,58 +133,58 @@ func (c *CoreString) Encode() string {
bitSize += entriesSize
}
var e = NewTCEncoder(make([]byte, bitSize/8))
var e = newTCEncoder(make([]byte, bitSize/8))
if bitSize%8 != 0 {
e = NewTCEncoder(make([]byte, bitSize/8+1))
e = newTCEncoder(make([]byte, bitSize/8+1))
}
e.WriteInt(c.Version, 6)
e.WriteTime(c.Created)
e.WriteTime(c.LastUpdated)
e.WriteInt(c.CmpId, 12)
e.WriteInt(c.CmpVersion, 12)
e.WriteInt(c.ConsentScreen, 6)
e.WriteIsoCode(c.ConsentLanguage)
e.WriteInt(c.VendorListVersion, 12)
e.WriteInt(c.TcfPolicyVersion, 6)
e.WriteBool(c.IsServiceSpecific)
e.WriteBool(c.UseNonStandardStacks)
e.writeInt(c.Version, 6)
e.writeTime(c.Created)
e.writeTime(c.LastUpdated)
e.writeInt(c.CmpId, 12)
e.writeInt(c.CmpVersion, 12)
e.writeInt(c.ConsentScreen, 6)
e.writeIsoCode(c.ConsentLanguage)
e.writeInt(c.VendorListVersion, 12)
e.writeInt(c.TcfPolicyVersion, 6)
e.writeBool(c.IsServiceSpecific)
e.writeBool(c.UseNonStandardStacks)
for i := 0; i < 12; i++ {
e.WriteBool(c.IsSpecialFeatureAllowed(i + 1))
e.writeBool(c.IsSpecialFeatureAllowed(i + 1))
}
for i := 0; i < 24; i++ {
e.WriteBool(c.IsPurposeAllowed(i + 1))
e.writeBool(c.IsPurposeAllowed(i + 1))
}
for i := 0; i < 24; i++ {
e.WriteBool(c.IsPurposeLIAllowed(i + 1))
e.writeBool(c.IsPurposeLIAllowed(i + 1))
}
e.WriteBool(c.PurposeOneTreatment)
e.WriteIsoCode(c.PublisherCC)
e.writeBool(c.PurposeOneTreatment)
e.writeIsoCode(c.PublisherCC)
e.WriteInt(c.MaxVendorId, 16)
e.WriteBool(c.IsRangeEncoding)
e.writeInt(c.MaxVendorId, 16)
e.writeBool(c.IsRangeEncoding)
if c.IsRangeEncoding {
e.WriteInt(len(c.RangeEntries), 12)
e.WriteRangeEntries(c.RangeEntries)
e.writeInt(len(c.RangeEntries), 12)
e.writeRangeEntries(c.RangeEntries)
} else {
for i := 0; i < c.MaxVendorId; i++ {
e.WriteBool(c.IsVendorAllowed(i + 1))
e.writeBool(c.IsVendorAllowed(i + 1))
}
}
e.WriteInt(c.MaxVendorIdLI, 16)
e.WriteBool(c.IsRangeEncodingLI)
e.writeInt(c.MaxVendorIdLI, 16)
e.writeBool(c.IsRangeEncodingLI)
if c.IsRangeEncodingLI {
e.WriteInt(len(c.RangeEntriesLI), 12)
e.WriteRangeEntries(c.RangeEntriesLI)
e.writeInt(len(c.RangeEntriesLI), 12)
e.writeRangeEntries(c.RangeEntriesLI)
} else {
for i := 0; i < c.MaxVendorIdLI; i++ {
e.WriteBool(c.IsVendorLIAllowed(i + 1))
e.writeBool(c.IsVendorLIAllowed(i + 1))
}
}
e.WriteInt(len(c.PubRestrictions), 12)
e.WritePubRestrictions(c.PubRestrictions)
e.writeInt(len(c.PubRestrictions), 12)
e.writePubRestrictions(c.PubRestrictions)
return base64.RawURLEncoding.EncodeToString(e.bytes)
}

View File

@@ -44,20 +44,20 @@ func (d *DisclosedVendors) Encode() string {
bitSize += d.MaxVendorId
}
var e = NewTCEncoder(make([]byte, bitSize/8))
var e = newTCEncoder(make([]byte, bitSize/8))
if bitSize%8 != 0 {
e = NewTCEncoder(make([]byte, bitSize/8+1))
e = newTCEncoder(make([]byte, bitSize/8+1))
}
e.WriteInt(d.SegmentType, 3)
e.WriteInt(d.MaxVendorId, 16)
e.WriteBool(d.IsRangeEncoding)
e.writeInt(d.SegmentType, 3)
e.writeInt(d.MaxVendorId, 16)
e.writeBool(d.IsRangeEncoding)
if d.IsRangeEncoding {
e.WriteInt(len(d.RangeEntries), 12)
e.WriteRangeEntries(d.RangeEntries)
e.writeInt(len(d.RangeEntries), 12)
e.writeRangeEntries(d.RangeEntries)
} else {
for i := 0; i < d.MaxVendorId; i++ {
e.WriteBool(d.IsVendorDisclosed(i + 1))
e.writeBool(d.IsVendorDisclosed(i + 1))
}
}

View File

@@ -30,24 +30,24 @@ func (p *PublisherTC) IsCustomPurposeLIAllowed(id int) bool {
func (p *PublisherTC) Encode() string {
bitSize := 57 + (p.NumCustomPurposes * 2)
var e = NewTCEncoder(make([]byte, bitSize/8))
var e = newTCEncoder(make([]byte, bitSize/8))
if bitSize%8 != 0 {
e = NewTCEncoder(make([]byte, bitSize/8+1))
e = newTCEncoder(make([]byte, bitSize/8+1))
}
e.WriteInt(p.SegmentType, 3)
e.writeInt(p.SegmentType, 3)
for i := 0; i < 24; i++ {
e.WriteBool(p.IsPurposeAllowed(i + 1))
e.writeBool(p.IsPurposeAllowed(i + 1))
}
for i := 0; i < 24; i++ {
e.WriteBool(p.IsPurposeLIAllowed(i + 1))
e.writeBool(p.IsPurposeLIAllowed(i + 1))
}
e.WriteInt(p.NumCustomPurposes, 6)
e.writeInt(p.NumCustomPurposes, 6)
for i := 0; i < p.NumCustomPurposes; i++ {
e.WriteBool(p.IsCustomPurposeAllowed(i + 1))
e.writeBool(p.IsCustomPurposeAllowed(i + 1))
}
for i := 0; i < p.NumCustomPurposes; i++ {
e.WriteBool(p.IsCustomPurposeLIAllowed(i + 1))
e.writeBool(p.IsCustomPurposeLIAllowed(i + 1))
}
return base64.RawURLEncoding.EncodeToString(e.bytes)

105
tcencoder.go Normal file
View File

@@ -0,0 +1,105 @@
package iabtcf
import (
"time"
)
const (
decisecondsPerSecond = 10
nanosecondsPerDecisecond = int64(time.Millisecond * 100)
)
type TCEncoder struct {
*Bits
}
func newTCEncoder(src []byte) *TCEncoder {
return &TCEncoder{newBits(src)}
}
func (r *TCEncoder) readTime() time.Time {
var ds = int64(r.readInt(36))
return time.Unix(ds/decisecondsPerSecond, (ds%decisecondsPerSecond)*nanosecondsPerDecisecond).UTC()
}
func (r *TCEncoder) writeTime(v time.Time) {
r.writeNumber(v.UnixNano()/nanosecondsPerDecisecond, 36)
}
func (r *TCEncoder) readIsoCode() string {
var buf = make([]byte, 0, 2)
for i := uint(0); i < 2; i++ {
buf = append(buf, byte(r.readInt(6))+'A')
}
return string(buf)
}
func (r *TCEncoder) writeIsoCode(v string) {
for _, char := range v {
r.writeInt(int(byte(char)-'A'), 6)
}
}
func (r *TCEncoder) readBitField(n uint) map[int]bool {
var m = make(map[int]bool)
for i := uint(0); i < n; i++ {
if r.readBool() {
m[int(i)+1] = true
}
}
return m
}
func (r *TCEncoder) writeRangeEntries(entries []*RangeEntry) {
for _, entry := range entries {
if entry.EndVendorID > entry.StartVendorID {
r.writeBool(true)
r.writeInt(entry.StartVendorID, 16)
r.writeInt(entry.EndVendorID, 16)
} else {
r.writeBool(false)
r.writeInt(entry.StartVendorID, 16)
}
}
}
func (r *TCEncoder) readRangeEntries(n uint) []*RangeEntry {
var ret = make([]*RangeEntry, 0, n)
for i := uint(0); i < n; i++ {
var isRange = r.readBool()
var start, end int
start = r.readInt(16)
if isRange {
end = r.readInt(16)
} else {
end = start
}
ret = append(ret, &RangeEntry{StartVendorID: start, EndVendorID: end})
}
return ret
}
func (r *TCEncoder) writePubRestrictions(entries []*PubRestriction) {
for _, entry := range entries {
r.writeInt(entry.PurposeId, 6)
r.writeInt(entry.RestrictionType, 2)
r.writeInt(len(entry.RangeEntries), 12)
r.writeRangeEntries(entry.RangeEntries)
}
}
func (r *TCEncoder) readPubRestrictions(n uint) []*PubRestriction {
var ret = make([]*PubRestriction, 0, n)
for i := uint(0); i < n; i++ {
var purposeId = r.readInt(6)
var restrictionType = r.readInt(2)
var numEntries = r.readInt(12)
var rangeEntries = r.readRangeEntries(uint(numEntries))
ret = append(ret, &PubRestriction{PurposeId: purposeId,
RestrictionType: restrictionType,
NumEntries: numEntries,
RangeEntries: rangeEntries,
})
}
return ret
}