scanoss 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -2
- package/build/main/sdk/Decompress/Decompressor/DecompressZips.js +3 -2
- package/build/main/sdk/Dependencies/LocalDependency/LocalDependency.js +4 -1
- package/build/main/sdk/Dependencies/LocalDependency/parsers/parser.spec.js +54 -1
- package/build/main/sdk/Dependencies/LocalDependency/parsers/pnpmParser.d.ts +2 -0
- package/build/main/sdk/Dependencies/LocalDependency/parsers/pnpmParser.js +257 -0
- package/build/main/sdk/Dependencies/LocalDependency/parsers/pyParser.d.ts +1 -0
- package/build/main/sdk/Dependencies/LocalDependency/parsers/pyParser.js +26 -9
- package/build/main/tsconfig.tsbuildinfo +1 -1
- package/build/module/sdk/Decompress/Decompressor/DecompressZips.js +3 -2
- package/build/module/sdk/Dependencies/LocalDependency/LocalDependency.js +5 -2
- package/build/module/sdk/Dependencies/LocalDependency/parsers/parser.spec.js +54 -1
- package/build/module/sdk/Dependencies/LocalDependency/parsers/pnpmParser.d.ts +2 -0
- package/build/module/sdk/Dependencies/LocalDependency/parsers/pnpmParser.js +251 -0
- package/build/module/sdk/Dependencies/LocalDependency/parsers/pyParser.d.ts +1 -0
- package/build/module/sdk/Dependencies/LocalDependency/parsers/pyParser.js +25 -9
- package/build/module/tsconfig.module.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { PackageURL } from "packageurl-js";
|
|
3
|
+
const PURL_TYPE = "npm";
|
|
4
|
+
const MANIFEST_FILE = "pnpm-lock.yaml";
|
|
5
|
+
// Regex for pnpm lockfile v5 format: /package-name/version or /@scope/package-name/version
|
|
6
|
+
// May include peer dep suffixes like /@scope/pkg/1.0.0_peer@2.0.0
|
|
7
|
+
const V5_PACKAGE_REGEX = /^\s{2,4}\/?(?<fullname>(?:@(?<scope>[^/]+)\/)?(?<name>[^/]+))\/(?<version>\d[^_:]*)/;
|
|
8
|
+
// Regex for pnpm lockfile v6+ format: /package-name@version or /@scope/package-name@version
|
|
9
|
+
// May include peer dep suffixes like /@scope/pkg@1.0.0(@peer/pkg@2.0.0)
|
|
10
|
+
const V6_PACKAGE_REGEX = /^\s{2,4}'?\/?(?<fullname>(?:@(?<scope>[^/@]+)\/)?(?<name>[^@']+))@(?<version>\d[^(':\s]*)/;
|
|
11
|
+
function parseLockfileVersion(fileContent) {
|
|
12
|
+
const match = fileContent.match(/^lockfileVersion:\s*'?(\d+)/m);
|
|
13
|
+
if (match)
|
|
14
|
+
return parseInt(match[1], 10);
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
// For pnpm v9+: Parse importers section to get direct prod/dev dependency resolved versions.
|
|
18
|
+
// Returns sets of package keys like "express@4.18.2" or "@angular/core@14.2.0".
|
|
19
|
+
function parseImportersDeps(lines) {
|
|
20
|
+
const prodKeys = new Set();
|
|
21
|
+
const devKeys = new Set();
|
|
22
|
+
let inImporters = false;
|
|
23
|
+
let currentTarget = null;
|
|
24
|
+
let pkgName = null;
|
|
25
|
+
for (const line of lines) {
|
|
26
|
+
const trimmed = line.trimEnd();
|
|
27
|
+
if (trimmed === '')
|
|
28
|
+
continue;
|
|
29
|
+
if (/^importers:\s*$/.test(trimmed)) {
|
|
30
|
+
inImporters = true;
|
|
31
|
+
currentTarget = null;
|
|
32
|
+
pkgName = null;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (!inImporters)
|
|
36
|
+
continue;
|
|
37
|
+
// End of importers section (next top-level key)
|
|
38
|
+
if (/^\S/.test(trimmed) && !trimmed.startsWith('#')) {
|
|
39
|
+
inImporters = false;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
const indent = line.search(/\S/);
|
|
43
|
+
// Workspace key at indent 2 (e.g., " .:" or " packages/app:")
|
|
44
|
+
if (indent === 2) {
|
|
45
|
+
currentTarget = null;
|
|
46
|
+
pkgName = null;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
// Section header at indent 4 (dependencies:, devDependencies:, etc.)
|
|
50
|
+
if (indent === 4) {
|
|
51
|
+
if (/^\s{4}dependencies:\s*$/.test(trimmed) || /^\s{4}optionalDependencies:\s*$/.test(trimmed)) {
|
|
52
|
+
currentTarget = prodKeys;
|
|
53
|
+
}
|
|
54
|
+
else if (/^\s{4}devDependencies:\s*$/.test(trimmed)) {
|
|
55
|
+
currentTarget = devKeys;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
currentTarget = null;
|
|
59
|
+
}
|
|
60
|
+
pkgName = null;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!currentTarget)
|
|
64
|
+
continue;
|
|
65
|
+
// Package name at indent 6 (e.g., " express:" or " '@angular/core':")
|
|
66
|
+
if (indent === 6) {
|
|
67
|
+
const match = trimmed.match(/^\s{6}'?([^':]+)'?:\s*$/);
|
|
68
|
+
if (match) {
|
|
69
|
+
pkgName = match[1];
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
// Version at indent 8 (e.g., " version: 4.18.2" or " version: 14.2.0(rxjs@7.8.0)")
|
|
74
|
+
if (indent === 8 && pkgName) {
|
|
75
|
+
const match = trimmed.match(/^\s{8}version:\s*'?([^'\s]+)'?\s*$/);
|
|
76
|
+
if (match) {
|
|
77
|
+
// Strip peer dep suffixes in parentheses
|
|
78
|
+
const version = match[1].replace(/\(.*$/, '');
|
|
79
|
+
currentTarget.add(`${pkgName}@${version}`);
|
|
80
|
+
pkgName = null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { prodKeys, devKeys };
|
|
85
|
+
}
|
|
86
|
+
// For pnpm v9+: Build dependency graph from snapshots section.
|
|
87
|
+
// Maps each package key (e.g., "express@4.18.2") to its dependency keys.
|
|
88
|
+
function buildSnapshotGraph(lines) {
|
|
89
|
+
const graph = new Map();
|
|
90
|
+
let inSnapshots = false;
|
|
91
|
+
let currentKey = null;
|
|
92
|
+
let inDeps = false;
|
|
93
|
+
for (const line of lines) {
|
|
94
|
+
const trimmed = line.trimEnd();
|
|
95
|
+
if (trimmed === '')
|
|
96
|
+
continue;
|
|
97
|
+
if (/^snapshots:\s*$/.test(trimmed)) {
|
|
98
|
+
inSnapshots = true;
|
|
99
|
+
currentKey = null;
|
|
100
|
+
inDeps = false;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (!inSnapshots)
|
|
104
|
+
continue;
|
|
105
|
+
// End of snapshots section (next top-level key)
|
|
106
|
+
if (/^\S/.test(trimmed) && !trimmed.startsWith('#')) {
|
|
107
|
+
inSnapshots = false;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
const indent = line.search(/\S/);
|
|
111
|
+
// Snapshot entry at indent 2 (e.g., " express@4.18.2:" or " lodash@4.17.21: {}")
|
|
112
|
+
if (indent === 2) {
|
|
113
|
+
const match = trimmed.match(/^\s{2}'?(.+?)(?:\([^)]*\))*'?:\s*(\{\})?\s*$/);
|
|
114
|
+
if (match) {
|
|
115
|
+
// Strip peer dep suffixes from key
|
|
116
|
+
currentKey = match[1].replace(/\(.*$/, '');
|
|
117
|
+
if (!graph.has(currentKey)) {
|
|
118
|
+
graph.set(currentKey, []);
|
|
119
|
+
}
|
|
120
|
+
inDeps = false;
|
|
121
|
+
// Empty entry like " lodash@4.17.21: {}"
|
|
122
|
+
if (match[2] === '{}') {
|
|
123
|
+
currentKey = null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (!currentKey)
|
|
129
|
+
continue;
|
|
130
|
+
// Subsection header at indent 4
|
|
131
|
+
if (indent === 4) {
|
|
132
|
+
inDeps = /^\s{4}(?:dependencies|optionalDependencies):\s*$/.test(trimmed);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
// Dependency entry at indent 6 (e.g., " accepts: 1.3.8")
|
|
136
|
+
if (indent === 6 && inDeps) {
|
|
137
|
+
const match = trimmed.match(/^\s{6}'?([^':]+)'?:\s*'?([^'\s]+)'?/);
|
|
138
|
+
if (match) {
|
|
139
|
+
const depVersion = match[2].replace(/\(.*$/, '');
|
|
140
|
+
const depKey = `${match[1]}@${depVersion}`;
|
|
141
|
+
graph.get(currentKey).push(depKey);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return graph;
|
|
146
|
+
}
|
|
147
|
+
// BFS from prod dependencies through the snapshot graph to find all production-reachable packages.
|
|
148
|
+
function findProductionPackages(prodKeys, graph) {
|
|
149
|
+
const visited = new Set();
|
|
150
|
+
const queue = [...prodKeys];
|
|
151
|
+
while (queue.length > 0) {
|
|
152
|
+
const key = queue.shift();
|
|
153
|
+
if (visited.has(key))
|
|
154
|
+
continue;
|
|
155
|
+
visited.add(key);
|
|
156
|
+
const deps = graph.get(key);
|
|
157
|
+
if (deps) {
|
|
158
|
+
for (const dep of deps) {
|
|
159
|
+
if (!visited.has(dep)) {
|
|
160
|
+
queue.push(dep);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return visited;
|
|
166
|
+
}
|
|
167
|
+
function parsePackagesSection(fileContent) {
|
|
168
|
+
const entries = [];
|
|
169
|
+
const lines = fileContent.split('\n');
|
|
170
|
+
const lockfileVersion = parseLockfileVersion(fileContent);
|
|
171
|
+
let inPackagesSection = false;
|
|
172
|
+
let currentEntry = null;
|
|
173
|
+
const packageRegex = lockfileVersion >= 6 ? V6_PACKAGE_REGEX : V5_PACKAGE_REGEX;
|
|
174
|
+
// For v9+, determine dev scope from importers + snapshots instead of dev: flag
|
|
175
|
+
let prodPackages = null;
|
|
176
|
+
if (lockfileVersion >= 9) {
|
|
177
|
+
const { prodKeys, devKeys } = parseImportersDeps(lines);
|
|
178
|
+
// Only use v9 logic if importers section was found; otherwise fall back to defaults
|
|
179
|
+
if (prodKeys.size > 0 || devKeys.size > 0) {
|
|
180
|
+
const graph = buildSnapshotGraph(lines);
|
|
181
|
+
prodPackages = findProductionPackages(prodKeys, graph);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
for (const line of lines) {
|
|
185
|
+
// Detect start of packages section
|
|
186
|
+
if (/^packages:/.test(line)) {
|
|
187
|
+
inPackagesSection = true;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
// Detect end of packages section (next top-level key)
|
|
191
|
+
if (inPackagesSection && /^\S/.test(line) && !line.startsWith('#')) {
|
|
192
|
+
// Save last entry
|
|
193
|
+
if (currentEntry)
|
|
194
|
+
entries.push(currentEntry);
|
|
195
|
+
inPackagesSection = false;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (!inPackagesSection)
|
|
199
|
+
continue;
|
|
200
|
+
// Try to match a package key line
|
|
201
|
+
const match = line.match(packageRegex);
|
|
202
|
+
if (match && match.groups) {
|
|
203
|
+
// Save previous entry
|
|
204
|
+
if (currentEntry)
|
|
205
|
+
entries.push(currentEntry);
|
|
206
|
+
const pkgScope = match.groups.scope || undefined;
|
|
207
|
+
const pkgName = match.groups.name;
|
|
208
|
+
const pkgVersion = match.groups.version;
|
|
209
|
+
let isDev = false;
|
|
210
|
+
if (lockfileVersion >= 9 && prodPackages) {
|
|
211
|
+
// For v9+, a package is dev if it's NOT reachable from production dependencies
|
|
212
|
+
const key = pkgScope ? `@${pkgScope}/${pkgName}@${pkgVersion}` : `${pkgName}@${pkgVersion}`;
|
|
213
|
+
isDev = !prodPackages.has(key);
|
|
214
|
+
}
|
|
215
|
+
currentEntry = {
|
|
216
|
+
scope: pkgScope,
|
|
217
|
+
name: pkgName,
|
|
218
|
+
version: pkgVersion,
|
|
219
|
+
dev: isDev,
|
|
220
|
+
};
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
// Check for dev flag within current entry (v5-v8 only)
|
|
224
|
+
if (lockfileVersion < 9 && currentEntry && /^\s+dev:\s*true/.test(line)) {
|
|
225
|
+
currentEntry.dev = true;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Don't forget last entry
|
|
229
|
+
if (currentEntry)
|
|
230
|
+
entries.push(currentEntry);
|
|
231
|
+
return entries;
|
|
232
|
+
}
|
|
233
|
+
export function pnpmLockParser(fileContent, filePath) {
|
|
234
|
+
const results = { file: filePath, purls: [] };
|
|
235
|
+
if (path.basename(filePath) != MANIFEST_FILE)
|
|
236
|
+
return Promise.resolve(results);
|
|
237
|
+
try {
|
|
238
|
+
const packages = parsePackagesSection(fileContent);
|
|
239
|
+
for (const pkg of packages) {
|
|
240
|
+
const namespace = pkg.scope ? `@${pkg.scope}` : undefined;
|
|
241
|
+
const purlString = new PackageURL(PURL_TYPE, namespace, pkg.name, pkg.version, undefined, undefined).toString();
|
|
242
|
+
const scope = pkg.dev ? "devDependencies" : "dependencies";
|
|
243
|
+
results.purls.push({ purl: purlString, requirement: pkg.version, scope: scope });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch (e) {
|
|
247
|
+
console.error(e);
|
|
248
|
+
}
|
|
249
|
+
return Promise.resolve(results);
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG5wbVBhcnNlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9zZGsvRGVwZW5kZW5jaWVzL0xvY2FsRGVwZW5kZW5jeS9wYXJzZXJzL3BucG1QYXJzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQ3hCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFHM0MsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDO0FBQ3hCLE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDO0FBRXZDLDJGQUEyRjtBQUMzRixrRUFBa0U7QUFDbEUsTUFBTSxnQkFBZ0IsR0FBRyxxRkFBcUYsQ0FBQztBQUUvRyw0RkFBNEY7QUFDNUYsd0VBQXdFO0FBQ3hFLE1BQU0sZ0JBQWdCLEdBQUcsMkZBQTJGLENBQUM7QUFTckgsU0FBUyxvQkFBb0IsQ0FBQyxXQUFtQjtJQUMvQyxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUM7SUFDaEUsSUFBSSxLQUFLO1FBQUUsT0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLE9BQU8sQ0FBQyxDQUFDO0FBQ1gsQ0FBQztBQUVELDZGQUE2RjtBQUM3RixnRkFBZ0Y7QUFDaEYsU0FBUyxrQkFBa0IsQ0FBQyxLQUFlO0lBQ3pDLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDbkMsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUVsQyxJQUFJLFdBQVcsR0FBRyxLQUFLLENBQUM7SUFDeEIsSUFBSSxhQUFhLEdBQXVCLElBQUksQ0FBQztJQUM3QyxJQUFJLE9BQU8sR0FBa0IsSUFBSSxDQUFDO0lBRWxDLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsTUFBTSxP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
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { ILocalDependency } from "../DependencyTypes";
|
|
2
2
|
export declare function requirementsParser(fileContent: string, filePath: string): Promise<ILocalDependency>;
|
|
3
|
+
export declare function pipRequirementsLockParser(fileContent: string, filePath: string): Promise<ILocalDependency>;
|
|
@@ -10,14 +10,8 @@ function parseDep(str) {
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
const PURL_TYPE = 'pypi';
|
|
13
|
-
|
|
14
|
-
// See reference on: https://pip.pypa.io/en/stable/reference/requirements-file-format/
|
|
15
|
-
const MANIFEST_FILE = 'requirements.txt';
|
|
16
|
-
export function requirementsParser(fileContent, filePath) {
|
|
17
|
-
// If the file is not a python manifest file, return an empty results
|
|
13
|
+
function parseRequirementsContent(fileContent, filePath) {
|
|
18
14
|
const results = { file: filePath, purls: [] };
|
|
19
|
-
if (path.basename(filePath) != MANIFEST_FILE)
|
|
20
|
-
return Promise.resolve(results);
|
|
21
15
|
const lines = fileContent.split('\n');
|
|
22
16
|
for (let line of lines) {
|
|
23
17
|
line = line.trim();
|
|
@@ -35,6 +29,9 @@ export function requirementsParser(fileContent, filePath) {
|
|
|
35
29
|
else if (line.startsWith('-r')) {
|
|
36
30
|
continue;
|
|
37
31
|
} // Recursive dependencies (NOT SUPPORTED YET)
|
|
32
|
+
else if (line.startsWith('-')) {
|
|
33
|
+
continue;
|
|
34
|
+
} // Skip pip options (e.g. --hash, -i, -e, etc.)
|
|
38
35
|
else {
|
|
39
36
|
const dep = parseDep(line);
|
|
40
37
|
if (!dep.sym) {
|
|
@@ -52,6 +49,25 @@ export function requirementsParser(fileContent, filePath) {
|
|
|
52
49
|
}
|
|
53
50
|
}
|
|
54
51
|
}
|
|
55
|
-
return
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
54
|
+
// Parse a requirements.txt file from python projects
|
|
55
|
+
// See reference on: https://pip.pypa.io/en/stable/reference/requirements-file-format/
|
|
56
|
+
const MANIFEST_FILE = 'requirements.txt';
|
|
57
|
+
export function requirementsParser(fileContent, filePath) {
|
|
58
|
+
// If the file is not a python manifest file, return an empty results
|
|
59
|
+
const results = { file: filePath, purls: [] };
|
|
60
|
+
if (path.basename(filePath) != MANIFEST_FILE)
|
|
61
|
+
return Promise.resolve(results);
|
|
62
|
+
return Promise.resolve(parseRequirementsContent(fileContent, filePath));
|
|
63
|
+
}
|
|
64
|
+
// Parse a pip_requirements_lock.txt file (pip-compile / pip-tools lock file)
|
|
65
|
+
// Same format as requirements.txt but typically with pinned versions (==)
|
|
66
|
+
const LOCK_MANIFEST_FILE = 'pip_requirements_lock.txt';
|
|
67
|
+
export function pipRequirementsLockParser(fileContent, filePath) {
|
|
68
|
+
const results = { file: filePath, purls: [] };
|
|
69
|
+
if (path.basename(filePath) != LOCK_MANIFEST_FILE)
|
|
70
|
+
return Promise.resolve(results);
|
|
71
|
+
return Promise.resolve(parseRequirementsContent(fileContent, filePath));
|
|
56
72
|
}
|
|
57
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
73
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHlQYXJzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvc2RrL0RlcGVuZGVuY2llcy9Mb2NhbERlcGVuZGVuY3kvcGFyc2Vycy9weVBhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUdsRCxTQUFTLFFBQVEsQ0FBRSxHQUFXO0lBQzVCLE1BQU0sR0FBRyxHQUFHLDBEQUEwRCxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqRixPQUFPO1FBQ0wsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsSUFBSTtRQUN2QixHQUFHLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxHQUFHO1FBQ3JCLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE9BQU87S0FDOUIsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUM7QUFFekIsU0FBUyx3QkFBd0IsQ0FBQyxXQUFtQixFQUFFLFFBQWdCO0lBQ25FLE1BQU0sT0FBTyxHQUFxQixFQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBQyxDQUFDO0lBQzlELE1BQU0sS0FBSyxHQUFrQixXQUFXLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRXJELEtBQUssSUFBSSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDckIsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNuQixJQUFHLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQztZQUFFLFNBQVM7UUFDOUIsSUFBRyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUks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
|