@btc-embedded/cdk-extensions 0.23.4 → 0.23.5
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/.jsii +5 -5
- package/CHANGELOG.md +7 -0
- package/assets/cli/catnip.js +154 -166
- package/lib/constructs/EventPipe.js +1 -1
- package/lib/constructs/ExportedService.js +1 -1
- package/lib/constructs/S3Bucket.js +1 -1
- package/lib/constructs/SecureRestApi.js +1 -1
- package/lib/constructs/SecureRestApiV2.js +1 -1
- package/lib/constructs/api-keys/ApiKeyClientAuthorization.js +1 -1
- package/lib/constructs/api-keys/ApiKeyManagement.js +1 -1
- package/lib/constructs/api-keys/ApiKeyPreTokenHandler.js +1 -1
- package/lib/constructs/api-keys/ApiKeyStore.js +1 -1
- package/lib/extensions/ApiGatewayExtension.js +1 -1
- package/lib/extensions/ApplicationContainer.js +1 -1
- package/lib/extensions/ApplicationLoadBalancerExtension.js +1 -1
- package/lib/extensions/ApplicationLoadBalancerExtensionV2.js +1 -1
- package/lib/extensions/CloudMapExtension.js +1 -1
- package/lib/extensions/DeactivatableServiceExtension.js +1 -1
- package/lib/extensions/DeploymentConfigExtension.js +1 -1
- package/lib/extensions/DocumentDbAccessExtension.js +1 -1
- package/lib/extensions/DomainEventMessagingExtension.js +1 -1
- package/lib/extensions/EfsMountExtension.js +1 -1
- package/lib/extensions/ExtraContainerExtension.js +1 -1
- package/lib/extensions/HTTPApiExtension.js +1 -1
- package/lib/extensions/LogExtension.js +1 -1
- package/lib/extensions/ModifyContainerDefinitionExtension.js +1 -1
- package/lib/extensions/ModifyTaskDefinitionExtension.js +1 -1
- package/lib/extensions/OpenIdExtension.js +1 -1
- package/lib/extensions/OpenTelemetryExtension.js +1 -1
- package/lib/extensions/PostgresDbAccessExtension.js +1 -1
- package/lib/extensions/SharedVolumeExtension.js +1 -1
- package/lib/extensions/TcpKeepAliveExtension.js +1 -1
- package/lib/platform/ApiGateway.js +1 -1
- package/lib/platform/ApiGatewayVpcLink.js +2 -2
- package/lib/platform/ApplicationLoadBalancer.js +1 -1
- package/lib/platform/ApplicationLoadBalancerV2.d.ts +1 -0
- package/lib/platform/ApplicationLoadBalancerV2.js +10 -3
- package/lib/platform/AuroraPostgresDB.js +2 -2
- package/lib/platform/BTCLogGroup.js +1 -1
- package/lib/platform/CognitoUserPool.js +2 -2
- package/lib/platform/DefaultUserPoolClients.js +1 -1
- package/lib/platform/DocumentDB.js +2 -2
- package/lib/platform/EcsCluster.js +1 -1
- package/lib/platform/EfsFileSystem.js +1 -1
- package/lib/platform/HostedZone.js +1 -1
- package/lib/platform/PrivateDnsNamespace.js +1 -1
- package/lib/platform/ResourceServer.js +1 -1
- package/lib/platform/Vpc.js +1 -1
- package/lib/platform/VpcV2.js +1 -1
- package/lib/stacks/ApplicationStack.js +1 -1
- package/lib/utils/BasePlatformStackResolver.js +1 -1
- package/lib/utils/StackParameter.js +1 -1
- package/node_modules/@nodable/entities/README.md +41 -0
- package/node_modules/@nodable/entities/package.json +54 -0
- package/node_modules/@nodable/entities/src/EntityDecoder.js +543 -0
- package/node_modules/@nodable/entities/src/EntityEncoder.js +194 -0
- package/node_modules/@nodable/entities/src/entities.js +1177 -0
- package/node_modules/@nodable/entities/src/entityTries.js +49 -0
- package/node_modules/@nodable/entities/src/index.d.ts +264 -0
- package/node_modules/@nodable/entities/src/index.js +29 -0
- package/node_modules/fast-xml-builder/CHANGELOG.md +40 -0
- package/node_modules/fast-xml-builder/LICENSE +21 -0
- package/node_modules/fast-xml-builder/README.md +74 -0
- package/node_modules/fast-xml-builder/lib/fxb.cjs +1 -0
- package/node_modules/fast-xml-builder/lib/fxb.d.cts +270 -0
- package/node_modules/fast-xml-builder/lib/fxb.min.js +2 -0
- package/node_modules/fast-xml-builder/lib/fxb.min.js.map +1 -0
- package/node_modules/fast-xml-builder/package.json +81 -0
- package/node_modules/fast-xml-builder/src/fxb.d.ts +270 -0
- package/node_modules/fast-xml-builder/src/fxb.js +599 -0
- package/node_modules/fast-xml-builder/src/ignoreAttributes.js +18 -0
- package/node_modules/fast-xml-builder/src/orderedJs2Xml.js +359 -0
- package/node_modules/fast-xml-builder/src/util.js +16 -0
- package/node_modules/fast-xml-parser/CHANGELOG.md +165 -0
- package/node_modules/fast-xml-parser/README.md +21 -44
- package/node_modules/fast-xml-parser/lib/fxbuilder.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxbuilder.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.cjs +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.d.cts +343 -31
- package/node_modules/fast-xml-parser/lib/fxp.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxparser.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxparser.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxvalidator.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxvalidator.min.js.map +1 -1
- package/node_modules/fast-xml-parser/package.json +13 -8
- package/node_modules/fast-xml-parser/src/fxp.d.ts +335 -30
- package/node_modules/fast-xml-parser/src/fxp.js +1 -1
- package/node_modules/fast-xml-parser/src/util.js +18 -25
- package/node_modules/fast-xml-parser/src/v6/EntitiesParser.js +89 -87
- package/node_modules/fast-xml-parser/src/v6/OptionsBuilder.js +10 -10
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/BaseOutputBuilder.js +23 -23
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsArrBuilder.js +29 -29
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsMinArrBuilder.js +1 -1
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsObjBuilder.js +39 -39
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/ParserOptionsBuilder.js +21 -21
- package/node_modules/fast-xml-parser/src/v6/XMLParser.js +22 -22
- package/node_modules/fast-xml-parser/src/v6/valueParsers/EntitiesParser.js +85 -85
- package/node_modules/fast-xml-parser/src/validator.js +34 -34
- package/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js +5 -284
- package/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js +335 -293
- package/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js +160 -43
- package/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js +540 -308
- package/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js +26 -26
- package/node_modules/fast-xml-parser/src/xmlparser/node2json.js +99 -41
- package/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js +10 -10
- package/node_modules/path-expression-matcher/LICENSE +21 -0
- package/node_modules/path-expression-matcher/README.md +872 -0
- package/node_modules/path-expression-matcher/lib/pem.cjs +1 -0
- package/node_modules/path-expression-matcher/lib/pem.d.cts +634 -0
- package/node_modules/path-expression-matcher/lib/pem.min.js +2 -0
- package/node_modules/path-expression-matcher/lib/pem.min.js.map +1 -0
- package/node_modules/path-expression-matcher/package.json +78 -0
- package/node_modules/path-expression-matcher/src/Expression.js +232 -0
- package/node_modules/path-expression-matcher/src/ExpressionSet.js +209 -0
- package/node_modules/path-expression-matcher/src/Matcher.js +570 -0
- package/node_modules/path-expression-matcher/src/index.d.ts +523 -0
- package/node_modules/path-expression-matcher/src/index.js +29 -0
- package/node_modules/strnum/CHANGELOG.md +12 -2
- package/node_modules/strnum/README.md +1 -0
- package/node_modules/strnum/package.json +5 -4
- package/node_modules/strnum/strnum.js +99 -65
- package/node_modules/xml-naming/README.md +189 -0
- package/node_modules/xml-naming/package.json +54 -0
- package/node_modules/xml-naming/src/index.d.ts +74 -0
- package/node_modules/xml-naming/src/index.js +270 -0
- package/package.json +3 -2
- package/renovate.json5 +1 -0
- package/node_modules/fast-xml-parser/src/xmlbuilder/orderedJs2Xml.js +0 -134
- package/node_modules/strnum/.github/SECURITY.md +0 -5
- package/node_modules/strnum/.vscode/launch.json +0 -25
- package/node_modules/strnum/algo.stflow +0 -84
- package/node_modules/strnum/strnum.test.js +0 -173
- package/node_modules/strnum/test.js +0 -9
- /package/node_modules/{fast-xml-parser/src/xmlbuilder → fast-xml-builder/src}/prettifyJs2Xml.js +0 -0
|
@@ -1,369 +1,411 @@
|
|
|
1
|
-
import {isName} from '
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{
|
|
14
|
-
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
1
|
+
import { qName as isName } from 'xml-naming';
|
|
2
|
+
|
|
3
|
+
export default class DocTypeReader {
|
|
4
|
+
constructor(options, xmlVersion) {
|
|
5
|
+
this.suppressValidationErr = !options;
|
|
6
|
+
this.options = options;
|
|
7
|
+
this.xmlVersion = xmlVersion || 1.0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
setXmlVersion(xmlVersion = 1.0) {
|
|
11
|
+
this.xmlVersion = xmlVersion;
|
|
12
|
+
}
|
|
13
|
+
readDocType(xmlData, i) {
|
|
14
|
+
const entities = Object.create(null);
|
|
15
|
+
let entityCount = 0;
|
|
16
|
+
|
|
17
|
+
if (xmlData[i + 3] === 'O' &&
|
|
18
|
+
xmlData[i + 4] === 'C' &&
|
|
19
|
+
xmlData[i + 5] === 'T' &&
|
|
20
|
+
xmlData[i + 6] === 'Y' &&
|
|
21
|
+
xmlData[i + 7] === 'P' &&
|
|
22
|
+
xmlData[i + 8] === 'E') {
|
|
23
|
+
i = i + 9;
|
|
24
|
+
let angleBracketsCount = 1;
|
|
25
|
+
let hasBody = false, comment = false;
|
|
26
|
+
let exp = "";
|
|
27
|
+
for (; i < xmlData.length; i++) {
|
|
28
|
+
if (xmlData[i] === '<' && !comment) { //Determine the tag type
|
|
29
|
+
if (hasBody && hasSeq(xmlData, "!ENTITY", i)) {
|
|
30
|
+
i += 7;
|
|
31
|
+
let entityName, val;
|
|
32
|
+
[entityName, val, i] = this.readEntityExp(xmlData, i + 1, this.suppressValidationErr);
|
|
33
|
+
if (val.indexOf("&") === -1) { //Parameter entities are not supported
|
|
34
|
+
if (this.options.enabled !== false &&
|
|
35
|
+
this.options.maxEntityCount != null &&
|
|
36
|
+
entityCount >= this.options.maxEntityCount) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Entity count (${entityCount + 1}) exceeds maximum allowed (${this.options.maxEntityCount})`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
//const escaped = entityName.replace(/[.\-+*:]/g, '\\.');
|
|
42
|
+
//const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
43
|
+
entities[entityName] = val;
|
|
44
|
+
entityCount++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (hasBody && hasSeq(xmlData, "!ELEMENT", i)) {
|
|
48
|
+
i += 8;//Not supported
|
|
49
|
+
const { index } = this.readElementExp(xmlData, i + 1);
|
|
50
|
+
i = index;
|
|
51
|
+
} else if (hasBody && hasSeq(xmlData, "!ATTLIST", i)) {
|
|
52
|
+
i += 8;//Not supported
|
|
53
|
+
// const {index} = this.readAttlistExp(xmlData,i+1);
|
|
54
|
+
// i = index;
|
|
55
|
+
} else if (hasBody && hasSeq(xmlData, "!NOTATION", i)) {
|
|
56
|
+
i += 9;//Not supported
|
|
57
|
+
const { index } = this.readNotationExp(xmlData, i + 1, this.suppressValidationErr);
|
|
58
|
+
i = index;
|
|
59
|
+
} else if (hasSeq(xmlData, "!--", i)) comment = true;
|
|
60
|
+
else throw new Error(`Invalid DOCTYPE`);
|
|
61
|
+
|
|
62
|
+
angleBracketsCount++;
|
|
63
|
+
exp = "";
|
|
64
|
+
} else if (xmlData[i] === '>') { //Read tag content
|
|
65
|
+
if (comment) {
|
|
66
|
+
if (xmlData[i - 1] === "-" && xmlData[i - 2] === "-") {
|
|
67
|
+
comment = false;
|
|
68
|
+
angleBracketsCount--;
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
51
71
|
angleBracketsCount--;
|
|
52
72
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
73
|
+
if (angleBracketsCount === 0) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
} else if (xmlData[i] === '[') {
|
|
77
|
+
hasBody = true;
|
|
78
|
+
} else {
|
|
79
|
+
exp += xmlData[i];
|
|
58
80
|
}
|
|
59
|
-
}else if( xmlData[i] === '['){
|
|
60
|
-
hasBody = true;
|
|
61
|
-
}else{
|
|
62
|
-
exp += xmlData[i];
|
|
63
81
|
}
|
|
82
|
+
if (angleBracketsCount !== 0) {
|
|
83
|
+
throw new Error(`Unclosed DOCTYPE`);
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
throw new Error(`Invalid Tag instead of DOCTYPE`);
|
|
64
87
|
}
|
|
65
|
-
|
|
66
|
-
throw new Error(`Unclosed DOCTYPE`);
|
|
67
|
-
}
|
|
68
|
-
}else{
|
|
69
|
-
throw new Error(`Invalid Tag instead of DOCTYPE`);
|
|
88
|
+
return { entities, i };
|
|
70
89
|
}
|
|
71
|
-
|
|
72
|
-
|
|
90
|
+
readEntityExp(xmlData, i) {
|
|
91
|
+
//External entities are not supported
|
|
92
|
+
// <!ENTITY ext SYSTEM "http://normal-website.com" >
|
|
73
93
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
index++;
|
|
77
|
-
}
|
|
78
|
-
return index;
|
|
79
|
-
};
|
|
94
|
+
//Parameter entities are not supported
|
|
95
|
+
// <!ENTITY entityname "&anotherElement;">
|
|
80
96
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
// <!ENTITY ext SYSTEM "http://normal-website.com" >
|
|
97
|
+
//Internal entities are supported
|
|
98
|
+
// <!ENTITY entityname "replacement text">
|
|
84
99
|
|
|
85
|
-
|
|
86
|
-
|
|
100
|
+
// Skip leading whitespace after <!ENTITY
|
|
101
|
+
i = skipWhitespace(xmlData, i);
|
|
87
102
|
|
|
88
|
-
|
|
89
|
-
|
|
103
|
+
// Read entity name
|
|
104
|
+
const startIndex = i;
|
|
105
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i]) && xmlData[i] !== '"' && xmlData[i] !== "'") {
|
|
106
|
+
i++;
|
|
107
|
+
}
|
|
108
|
+
let entityName = xmlData.substring(startIndex, i);
|
|
90
109
|
|
|
91
|
-
|
|
92
|
-
i = skipWhitespace(xmlData, i);
|
|
110
|
+
validateEntityName(entityName, { xmlVersion: this.xmlVersion });
|
|
93
111
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
while (i < xmlData.length && !/\s/.test(xmlData[i]) && xmlData[i] !== '"' && xmlData[i] !== "'") {
|
|
97
|
-
entityName += xmlData[i];
|
|
98
|
-
i++;
|
|
99
|
-
}
|
|
100
|
-
validateEntityName(entityName);
|
|
112
|
+
// Skip whitespace after entity name
|
|
113
|
+
i = skipWhitespace(xmlData, i);
|
|
101
114
|
|
|
102
|
-
|
|
103
|
-
|
|
115
|
+
// Check for unsupported constructs (external entities or parameter entities)
|
|
116
|
+
if (!this.suppressValidationErr) {
|
|
117
|
+
if (xmlData.substring(i, i + 6).toUpperCase() === "SYSTEM") {
|
|
118
|
+
throw new Error("External entities are not supported");
|
|
119
|
+
} else if (xmlData[i] === "%") {
|
|
120
|
+
throw new Error("Parameter entities are not supported");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
104
123
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
124
|
+
// Read entity value (internal entity)
|
|
125
|
+
let entityValue = "";
|
|
126
|
+
[i, entityValue] = this.readIdentifierVal(xmlData, i, "entity");
|
|
127
|
+
|
|
128
|
+
// Validate entity size
|
|
129
|
+
if (this.options.enabled !== false &&
|
|
130
|
+
this.options.maxEntitySize != null &&
|
|
131
|
+
entityValue.length > this.options.maxEntitySize) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`Entity "${entityName}" size (${entityValue.length}) exceeds maximum allowed size (${this.options.maxEntitySize})`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
i--;
|
|
138
|
+
return [entityName, entityValue, i];
|
|
110
139
|
}
|
|
111
140
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
i--;
|
|
116
|
-
return [entityName, entityValue, i ];
|
|
117
|
-
}
|
|
141
|
+
readNotationExp(xmlData, i) {
|
|
142
|
+
// Skip leading whitespace after <!NOTATION
|
|
143
|
+
i = skipWhitespace(xmlData, i);
|
|
118
144
|
|
|
119
|
-
|
|
120
|
-
// Skip leading whitespace after <!NOTATION
|
|
121
|
-
i = skipWhitespace(xmlData, i);
|
|
145
|
+
// Read notation name
|
|
122
146
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
i
|
|
128
|
-
}
|
|
129
|
-
validateEntityName(notationName);
|
|
147
|
+
const startIndex = i;
|
|
148
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
149
|
+
i++;
|
|
150
|
+
}
|
|
151
|
+
let notationName = xmlData.substring(startIndex, i);
|
|
130
152
|
|
|
131
|
-
|
|
132
|
-
i = skipWhitespace(xmlData, i);
|
|
153
|
+
!this.suppressValidationErr && validateEntityName(notationName, { xmlVersion: this.xmlVersion });
|
|
133
154
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (identifierType !== "SYSTEM" && identifierType !== "PUBLIC") {
|
|
137
|
-
throw new Error(`Expected SYSTEM or PUBLIC, found "${identifierType}"`);
|
|
138
|
-
}
|
|
139
|
-
i += identifierType.length;
|
|
155
|
+
// Skip whitespace after notation name
|
|
156
|
+
i = skipWhitespace(xmlData, i);
|
|
140
157
|
|
|
141
|
-
|
|
142
|
-
|
|
158
|
+
// Check identifier type (SYSTEM or PUBLIC)
|
|
159
|
+
const identifierType = xmlData.substring(i, i + 6).toUpperCase();
|
|
160
|
+
if (!this.suppressValidationErr && identifierType !== "SYSTEM" && identifierType !== "PUBLIC") {
|
|
161
|
+
throw new Error(`Expected SYSTEM or PUBLIC, found "${identifierType}"`);
|
|
162
|
+
}
|
|
163
|
+
i += identifierType.length;
|
|
143
164
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
let systemIdentifier = null;
|
|
165
|
+
// Skip whitespace after identifier type
|
|
166
|
+
i = skipWhitespace(xmlData, i);
|
|
147
167
|
|
|
148
|
-
|
|
149
|
-
|
|
168
|
+
// Read public identifier (if PUBLIC)
|
|
169
|
+
let publicIdentifier = null;
|
|
170
|
+
let systemIdentifier = null;
|
|
150
171
|
|
|
151
|
-
|
|
152
|
-
|
|
172
|
+
if (identifierType === "PUBLIC") {
|
|
173
|
+
[i, publicIdentifier] = this.readIdentifierVal(xmlData, i, "publicIdentifier");
|
|
153
174
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
175
|
+
// Skip whitespace after public identifier
|
|
176
|
+
i = skipWhitespace(xmlData, i);
|
|
177
|
+
|
|
178
|
+
// Optionally read system identifier
|
|
179
|
+
if (xmlData[i] === '"' || xmlData[i] === "'") {
|
|
180
|
+
[i, systemIdentifier] = this.readIdentifierVal(xmlData, i, "systemIdentifier");
|
|
181
|
+
}
|
|
182
|
+
} else if (identifierType === "SYSTEM") {
|
|
183
|
+
// Read system identifier (mandatory for SYSTEM)
|
|
184
|
+
[i, systemIdentifier] = this.readIdentifierVal(xmlData, i, "systemIdentifier");
|
|
161
185
|
|
|
162
|
-
|
|
163
|
-
|
|
186
|
+
if (!this.suppressValidationErr && !systemIdentifier) {
|
|
187
|
+
throw new Error("Missing mandatory system identifier for SYSTEM notation");
|
|
188
|
+
}
|
|
164
189
|
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return {notationName, publicIdentifier, systemIdentifier, index: --i};
|
|
168
|
-
}
|
|
169
190
|
|
|
170
|
-
|
|
171
|
-
let identifierVal = "";
|
|
172
|
-
const startChar = xmlData[i];
|
|
173
|
-
if (startChar !== '"' && startChar !== "'") {
|
|
174
|
-
throw new Error(`Expected quoted string, found "${startChar}"`);
|
|
191
|
+
return { notationName, publicIdentifier, systemIdentifier, index: --i };
|
|
175
192
|
}
|
|
176
|
-
i++;
|
|
177
193
|
|
|
178
|
-
|
|
179
|
-
identifierVal
|
|
194
|
+
readIdentifierVal(xmlData, i, type) {
|
|
195
|
+
let identifierVal = "";
|
|
196
|
+
const startChar = xmlData[i];
|
|
197
|
+
if (startChar !== '"' && startChar !== "'") {
|
|
198
|
+
throw new Error(`Expected quoted string, found "${startChar}"`);
|
|
199
|
+
}
|
|
180
200
|
i++;
|
|
181
|
-
}
|
|
182
201
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
202
|
+
const startIndex = i;
|
|
203
|
+
while (i < xmlData.length && xmlData[i] !== startChar) {
|
|
204
|
+
i++;
|
|
205
|
+
}
|
|
206
|
+
identifierVal = xmlData.substring(startIndex, i);
|
|
189
207
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
// <!ELEMENT title (#PCDATA)>
|
|
194
|
-
// <!ELEMENT book (title, author+)>
|
|
195
|
-
// <!ELEMENT name (content-model)>
|
|
196
|
-
|
|
197
|
-
// Skip leading whitespace after <!ELEMENT
|
|
198
|
-
i = skipWhitespace(xmlData, i);
|
|
199
|
-
|
|
200
|
-
// Read element name
|
|
201
|
-
let elementName = "";
|
|
202
|
-
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
203
|
-
elementName += xmlData[i];
|
|
208
|
+
if (xmlData[i] !== startChar) {
|
|
209
|
+
throw new Error(`Unterminated ${type} value`);
|
|
210
|
+
}
|
|
204
211
|
i++;
|
|
212
|
+
return [i, identifierVal];
|
|
205
213
|
}
|
|
206
214
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
215
|
+
readElementExp(xmlData, i) {
|
|
216
|
+
// <!ELEMENT br EMPTY>
|
|
217
|
+
// <!ELEMENT div ANY>
|
|
218
|
+
// <!ELEMENT title (#PCDATA)>
|
|
219
|
+
// <!ELEMENT book (title, author+)>
|
|
220
|
+
// <!ELEMENT name (content-model)>
|
|
221
|
+
|
|
222
|
+
// Skip leading whitespace after <!ELEMENT
|
|
223
|
+
i = skipWhitespace(xmlData, i);
|
|
211
224
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
// Expect '(' to start content model
|
|
216
|
-
if(xmlData[i] === "E" && hasSeq(xmlData, "MPTY",i)) i+=4;
|
|
217
|
-
else if(xmlData[i] === "A" && hasSeq(xmlData, "NY",i)) i+=2;
|
|
218
|
-
else if (xmlData[i] === "(") {
|
|
219
|
-
i++; // Move past '('
|
|
220
|
-
|
|
221
|
-
// Read content model
|
|
222
|
-
while (i < xmlData.length && xmlData[i] !== ")") {
|
|
223
|
-
contentModel += xmlData[i];
|
|
225
|
+
// Read element name
|
|
226
|
+
const startIndex = i;
|
|
227
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
224
228
|
i++;
|
|
225
229
|
}
|
|
226
|
-
|
|
227
|
-
|
|
230
|
+
let elementName = xmlData.substring(startIndex, i);
|
|
231
|
+
|
|
232
|
+
// Validate element name
|
|
233
|
+
if (!this.suppressValidationErr && !isName(elementName, { xmlVersion: this.xmlVersion })) {
|
|
234
|
+
throw new Error(`Invalid element name: "${elementName}"`);
|
|
228
235
|
}
|
|
229
236
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
// Skip whitespace after element name
|
|
238
|
+
i = skipWhitespace(xmlData, i);
|
|
239
|
+
let contentModel = "";
|
|
240
|
+
// Expect '(' to start content model
|
|
241
|
+
if (xmlData[i] === "E" && hasSeq(xmlData, "MPTY", i)) i += 4;
|
|
242
|
+
else if (xmlData[i] === "A" && hasSeq(xmlData, "NY", i)) i += 2;
|
|
243
|
+
else if (xmlData[i] === "(") {
|
|
244
|
+
i++; // Move past '('
|
|
245
|
+
|
|
246
|
+
// Read content model
|
|
247
|
+
const startIndex = i;
|
|
248
|
+
while (i < xmlData.length && xmlData[i] !== ")") {
|
|
249
|
+
i++;
|
|
250
|
+
}
|
|
251
|
+
contentModel = xmlData.substring(startIndex, i);
|
|
240
252
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
253
|
+
if (xmlData[i] !== ")") {
|
|
254
|
+
throw new Error("Unterminated content model");
|
|
255
|
+
}
|
|
244
256
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
257
|
+
} else if (!this.suppressValidationErr) {
|
|
258
|
+
throw new Error(`Invalid Element Expression, found "${xmlData[i]}"`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
elementName,
|
|
263
|
+
contentModel: contentModel.trim(),
|
|
264
|
+
index: i
|
|
265
|
+
};
|
|
250
266
|
}
|
|
251
267
|
|
|
252
|
-
|
|
253
|
-
|
|
268
|
+
readAttlistExp(xmlData, i) {
|
|
269
|
+
// Skip leading whitespace after <!ATTLIST
|
|
270
|
+
i = skipWhitespace(xmlData, i);
|
|
254
271
|
|
|
255
|
-
|
|
256
|
-
|
|
272
|
+
// Read element name
|
|
273
|
+
let startIndex = i;
|
|
274
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
275
|
+
i++;
|
|
276
|
+
}
|
|
277
|
+
let elementName = xmlData.substring(startIndex, i);
|
|
257
278
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
261
|
-
attributeName += xmlData[i];
|
|
262
|
-
i++;
|
|
263
|
-
}
|
|
279
|
+
// Validate element name
|
|
280
|
+
validateEntityName(elementName, { xmlVersion: this.xmlVersion })
|
|
264
281
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
throw new Error(`Invalid attribute name: "${attributeName}"`);
|
|
268
|
-
}
|
|
282
|
+
// Skip whitespace after element name
|
|
283
|
+
i = skipWhitespace(xmlData, i);
|
|
269
284
|
|
|
270
|
-
|
|
271
|
-
|
|
285
|
+
// Read attribute name
|
|
286
|
+
startIndex = i;
|
|
287
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
288
|
+
i++;
|
|
289
|
+
}
|
|
290
|
+
let attributeName = xmlData.substring(startIndex, i);
|
|
272
291
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
i += 8; // Move past "NOTATION"
|
|
292
|
+
// Validate attribute name
|
|
293
|
+
if (!validateEntityName(attributeName, { xmlVersion: this.xmlVersion })) {
|
|
294
|
+
throw new Error(`Invalid attribute name: "${attributeName}"`);
|
|
295
|
+
}
|
|
278
296
|
|
|
279
|
-
// Skip whitespace after
|
|
297
|
+
// Skip whitespace after attribute name
|
|
280
298
|
i = skipWhitespace(xmlData, i);
|
|
281
299
|
|
|
282
|
-
//
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
i++;
|
|
300
|
+
// Read attribute type
|
|
301
|
+
let attributeType = "";
|
|
302
|
+
if (xmlData.substring(i, i + 8).toUpperCase() === "NOTATION") {
|
|
303
|
+
attributeType = "NOTATION";
|
|
304
|
+
i += 8; // Move past "NOTATION"
|
|
305
|
+
|
|
306
|
+
// Skip whitespace after "NOTATION"
|
|
307
|
+
i = skipWhitespace(xmlData, i);
|
|
308
|
+
|
|
309
|
+
// Expect '(' to start the list of notations
|
|
310
|
+
if (xmlData[i] !== "(") {
|
|
311
|
+
throw new Error(`Expected '(', found "${xmlData[i]}"`);
|
|
295
312
|
}
|
|
313
|
+
i++; // Move past '('
|
|
296
314
|
|
|
297
|
-
//
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
315
|
+
// Read the list of allowed notations
|
|
316
|
+
let allowedNotations = [];
|
|
317
|
+
while (i < xmlData.length && xmlData[i] !== ")") {
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
const startIndex = i;
|
|
321
|
+
while (i < xmlData.length && xmlData[i] !== "|" && xmlData[i] !== ")") {
|
|
322
|
+
i++;
|
|
323
|
+
}
|
|
324
|
+
let notation = xmlData.substring(startIndex, i);
|
|
325
|
+
|
|
326
|
+
// Validate notation name
|
|
327
|
+
notation = notation.trim();
|
|
328
|
+
if (!validateEntityName(notation, { xmlVersion: this.xmlVersion })) {
|
|
329
|
+
throw new Error(`Invalid notation name: "${notation}"`);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
allowedNotations.push(notation);
|
|
333
|
+
|
|
334
|
+
// Skip '|' separator or exit loop
|
|
335
|
+
if (xmlData[i] === "|") {
|
|
336
|
+
i++; // Move past '|'
|
|
337
|
+
i = skipWhitespace(xmlData, i); // Skip optional whitespace after '|'
|
|
338
|
+
}
|
|
301
339
|
}
|
|
302
340
|
|
|
303
|
-
|
|
341
|
+
if (xmlData[i] !== ")") {
|
|
342
|
+
throw new Error("Unterminated list of notations");
|
|
343
|
+
}
|
|
344
|
+
i++; // Move past ')'
|
|
345
|
+
|
|
346
|
+
// Store the allowed notations as part of the attribute type
|
|
347
|
+
attributeType += " (" + allowedNotations.join("|") + ")";
|
|
348
|
+
} else {
|
|
349
|
+
// Handle simple types (e.g., CDATA, ID, IDREF, etc.)
|
|
350
|
+
const startIndex = i;
|
|
351
|
+
while (i < xmlData.length && !/\s/.test(xmlData[i])) {
|
|
352
|
+
i++;
|
|
353
|
+
}
|
|
354
|
+
attributeType += xmlData.substring(startIndex, i);
|
|
304
355
|
|
|
305
|
-
//
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
356
|
+
// Validate simple attribute type
|
|
357
|
+
const validTypes = ["CDATA", "ID", "IDREF", "IDREFS", "ENTITY", "ENTITIES", "NMTOKEN", "NMTOKENS"];
|
|
358
|
+
if (!this.suppressValidationErr && !validTypes.includes(attributeType.toUpperCase())) {
|
|
359
|
+
throw new Error(`Invalid attribute type: "${attributeType}"`);
|
|
309
360
|
}
|
|
310
361
|
}
|
|
311
362
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
i++; // Move past ')'
|
|
363
|
+
// Skip whitespace after attribute type
|
|
364
|
+
i = skipWhitespace(xmlData, i);
|
|
316
365
|
|
|
317
|
-
//
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
366
|
+
// Read default value
|
|
367
|
+
let defaultValue = "";
|
|
368
|
+
if (xmlData.substring(i, i + 8).toUpperCase() === "#REQUIRED") {
|
|
369
|
+
defaultValue = "#REQUIRED";
|
|
370
|
+
i += 8;
|
|
371
|
+
} else if (xmlData.substring(i, i + 7).toUpperCase() === "#IMPLIED") {
|
|
372
|
+
defaultValue = "#IMPLIED";
|
|
373
|
+
i += 7;
|
|
374
|
+
} else {
|
|
375
|
+
[i, defaultValue] = this.readIdentifierVal(xmlData, i, "ATTLIST");
|
|
324
376
|
}
|
|
325
377
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
378
|
+
return {
|
|
379
|
+
elementName,
|
|
380
|
+
attributeName,
|
|
381
|
+
attributeType,
|
|
382
|
+
defaultValue,
|
|
383
|
+
index: i
|
|
330
384
|
}
|
|
331
385
|
}
|
|
386
|
+
}
|
|
387
|
+
|
|
332
388
|
|
|
333
|
-
// Skip whitespace after attribute type
|
|
334
|
-
i = skipWhitespace(xmlData, i);
|
|
335
|
-
|
|
336
|
-
// Read default value
|
|
337
|
-
let defaultValue = "";
|
|
338
|
-
if (xmlData.substring(i, i + 8).toUpperCase() === "#REQUIRED") {
|
|
339
|
-
defaultValue = "#REQUIRED";
|
|
340
|
-
i += 8;
|
|
341
|
-
} else if (xmlData.substring(i, i + 7).toUpperCase() === "#IMPLIED") {
|
|
342
|
-
defaultValue = "#IMPLIED";
|
|
343
|
-
i += 7;
|
|
344
|
-
} else {
|
|
345
|
-
[i, defaultValue] = readIdentifierVal(xmlData, i, "ATTLIST");
|
|
346
|
-
}
|
|
347
389
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
attributeType,
|
|
352
|
-
defaultValue,
|
|
353
|
-
index: i
|
|
390
|
+
const skipWhitespace = (data, index) => {
|
|
391
|
+
while (index < data.length && /\s/.test(data[index])) {
|
|
392
|
+
index++;
|
|
354
393
|
}
|
|
355
|
-
|
|
394
|
+
return index;
|
|
395
|
+
};
|
|
356
396
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
function hasSeq(data, seq, i) {
|
|
400
|
+
for (let j = 0; j < seq.length; j++) {
|
|
401
|
+
if (seq[j] !== data[i + j + 1]) return false;
|
|
360
402
|
}
|
|
361
403
|
return true;
|
|
362
404
|
}
|
|
363
405
|
|
|
364
|
-
function validateEntityName(name){
|
|
365
|
-
if (isName(name))
|
|
366
|
-
|
|
406
|
+
function validateEntityName(name, xmlVersion) {
|
|
407
|
+
if (isName(name, { xmlVersion: xmlVersion }))
|
|
408
|
+
return name;
|
|
367
409
|
else
|
|
368
410
|
throw new Error(`Invalid entity name ${name}`);
|
|
369
|
-
}
|
|
411
|
+
}
|