Skip to content

Commit 8d81c3e

Browse files
Add parser
1 parent 56d0bc0 commit 8d81c3e

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed

.eslintrc.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
module.exports = {
2+
extends: "eslint:all",
3+
4+
rules: {
5+
"array-bracket-newline": "off",
6+
"array-element-newline": "off",
7+
"func-names": "off",
8+
"function-call-argument-newline": "off",
9+
"max-len": "off",
10+
"max-lines-per-function": "off",
11+
"multiline-ternary": "off",
12+
"no-invalid-this": "off",
13+
"no-magic-numbers": "off",
14+
"no-ternary": "off",
15+
"no-var": "off",
16+
"one-var": "off",
17+
"padded-blocks": "off",
18+
"prefer-arrow-callback": "off",
19+
"quote-props": "off",
20+
"require-unicode-regexp": "off",
21+
"sort-keys": "off",
22+
"vars-on-top": "off"
23+
}
24+
};

tc-string-parse.js

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/* eslint-env amd, node, browser */
2+
3+
"use strict";
4+
5+
(function (root, factory) {
6+
if (typeof define === "function" && define.amd) {
7+
define([], factory);
8+
} else if (typeof module === "object" && module.exports) {
9+
module.exports = factory();
10+
} else {
11+
root.TCStringParse = factory();
12+
}
13+
}(typeof self === "undefined" ? this : self, function () {
14+
var decodeBase64 = function (str) {
15+
if (typeof atob === "function") {
16+
return atob(str);
17+
}
18+
19+
return Buffer.from(str, "base64").toString("binary");
20+
};
21+
22+
var decodeToBinary = function (str) {
23+
var result = "";
24+
25+
for (var index = 0; index < str.length; index += 1) {
26+
var bits = str.charCodeAt(index).toString(2);
27+
var pad = "0".repeat(8 - bits.length);
28+
result += pad + bits;
29+
}
30+
31+
return result;
32+
};
33+
34+
var decodeBinaryToInt = function (bits) {
35+
return parseInt(bits, 2);
36+
};
37+
38+
var decodeDate = function (bits) {
39+
var date = new Date();
40+
var time = decodeBinaryToInt(bits) * 100;
41+
date.setTime(time);
42+
return date;
43+
};
44+
45+
var decodeBoolean = function (bit) {
46+
return Boolean(Number(bit));
47+
};
48+
49+
var decodeFlags = function (bits) {
50+
return bits.
51+
split("").
52+
reduce(function (result, bit, index) {
53+
if (decodeBoolean(bit)) {
54+
result[index + 1] = true;
55+
}
56+
57+
return result;
58+
}, {});
59+
};
60+
61+
var decodeBinaryToLanguageCode = function (bits) {
62+
var charOffset = "A".charCodeAt();
63+
64+
return bits.
65+
match(/.{6}/g).
66+
reduce(function (result, block) {
67+
var char = String.fromCharCode(decodeBinaryToInt(block) + charOffset);
68+
return result + char;
69+
}, "");
70+
};
71+
72+
var stringSchema = [{
73+
key: "core",
74+
data: [{
75+
key: "version",
76+
size: 6
77+
}, {
78+
key: "created",
79+
size: 36,
80+
decoder: decodeDate
81+
}, {
82+
key: "lastUpdated",
83+
size: 36,
84+
decoder: decodeDate
85+
}, {
86+
key: "cmpId",
87+
size: 12
88+
}, {
89+
key: "cmpVersion",
90+
size: 12
91+
}, {
92+
key: "consentScreen",
93+
size: 6
94+
}, {
95+
key: "consentLanguage",
96+
size: 12,
97+
decoder: decodeBinaryToLanguageCode
98+
}, {
99+
key: "vendorListVersion",
100+
size: 12
101+
}, {
102+
key: "policyVersion",
103+
size: 6
104+
}, {
105+
key: "isServiceSpecified",
106+
size: 1,
107+
decoder: decodeBoolean
108+
}, {
109+
key: "useNonStandardStacks",
110+
size: 1,
111+
decoder: decodeBoolean
112+
}, {
113+
key: "specialFeatureOptIns",
114+
size: 12,
115+
decoder: decodeFlags
116+
}, {
117+
key: "purposesConsents",
118+
size: 24,
119+
decoder: decodeFlags
120+
}, {
121+
key: "purposeLegitimateInterests",
122+
size: 24,
123+
decoder: decodeFlags
124+
}]
125+
}];
126+
127+
return function (str) {
128+
if (typeof str !== "string") {
129+
throw new Error("Invalid transparency and consent string specified");
130+
}
131+
132+
var segments = str.
133+
split(".").
134+
map(function (segment) {
135+
return decodeToBinary(decodeBase64(segment));
136+
});
137+
138+
if (decodeBinaryToInt(segments[0].slice(0, 6)) !== 2) {
139+
throw new Error("Unsupported transparency and consent version");
140+
}
141+
142+
return stringSchema.
143+
reduce(function (result, block, index) {
144+
var segment = segments[index];
145+
if (segment) {
146+
var bitOffset = 0;
147+
148+
result[block.key] = block.data.
149+
reduce(function (blockModel, data) {
150+
var bits = segment.slice(bitOffset, bitOffset + data.size);
151+
blockModel[data.key] = (data.decoder || decodeBinaryToInt)(bits);
152+
bitOffset += data.size;
153+
154+
return blockModel;
155+
}, {});
156+
}
157+
158+
return result;
159+
}, {});
160+
};
161+
}));

0 commit comments

Comments
 (0)