@@ -22,7 +22,7 @@ export default function readDocType(xmlData, i){
22
22
let entityName , val ;
23
23
[ entityName , val , i ] = readEntityExp ( xmlData , i + 1 ) ;
24
24
if ( val . indexOf ( "&" ) === - 1 ) //Parameter entities are not supported
25
- entities [ validateEntityName ( entityName ) ] = {
25
+ entities [ entityName ] = {
26
26
regx : RegExp ( `&${ entityName } ;` , "g" ) ,
27
27
val : val
28
28
} ;
@@ -62,7 +62,14 @@ export default function readDocType(xmlData, i){
62
62
return { entities, i} ;
63
63
}
64
64
65
- function readEntityExp ( xmlData , i ) {
65
+ const skipWhitespace = ( data , index ) => {
66
+ while ( index < data . length && / \s / . test ( data [ index ] ) ) {
67
+ index ++ ;
68
+ }
69
+ return index ;
70
+ } ;
71
+
72
+ function readEntityExp ( xmlData , i ) {
66
73
//External entities are not supported
67
74
// <!ENTITY ext SYSTEM "http://normal-website.com" >
68
75
@@ -71,26 +78,53 @@ function readEntityExp(xmlData,i){
71
78
72
79
//Internal entities are supported
73
80
// <!ENTITY entityname "replacement text">
74
-
75
- //read EntityName
81
+
82
+ // Skip leading whitespace after <!ENTITY
83
+ i = skipWhitespace ( xmlData , i ) ;
84
+
85
+ // Read entity name
76
86
let entityName = "" ;
77
- for ( ; i < xmlData . length && ( xmlData [ i ] !== "'" && xmlData [ i ] !== '"' ) ; i ++ ) {
78
- // if(xmlData[i] === " ") continue;
79
- // else
87
+ while ( i < xmlData . length && ! / \s / . test ( xmlData [ i ] ) && xmlData [ i ] !== '"' && xmlData [ i ] !== "'" ) {
80
88
entityName += xmlData [ i ] ;
89
+ i ++ ;
81
90
}
82
- entityName = entityName . trim ( ) ;
83
- if ( entityName . indexOf ( " " ) !== - 1 ) throw new Error ( "External entites are not supported" ) ;
84
-
85
- //read Entity Value
86
- const startChar = xmlData [ i ++ ] ;
87
- let val = ""
88
- for ( ; i < xmlData . length && xmlData [ i ] !== startChar ; i ++ ) {
89
- val += xmlData [ i ] ;
91
+
92
+ // Validate entity name
93
+ if ( ! validateEntityName ( entityName ) ) {
94
+ throw new Error ( `Invalid entity name: "${ entityName } "` ) ;
95
+ }
96
+
97
+ // Skip whitespace after entity name
98
+ i = skipWhitespace ( xmlData , i ) ;
99
+
100
+ // Check for unsupported constructs (external entities or parameter entities)
101
+ if ( xmlData . substring ( i , i + 6 ) . toUpperCase ( ) === "SYSTEM" ) {
102
+ throw new Error ( "External entities are not supported" ) ;
103
+ } else if ( xmlData [ i ] === "%" ) {
104
+ throw new Error ( "Parameter entities are not supported" ) ;
90
105
}
91
- return [ entityName , val , i ] ;
106
+
107
+ // Read entity value (internal entity)
108
+ const quoteChar = xmlData [ i ] ;
109
+ if ( quoteChar !== '"' && quoteChar !== "'" ) {
110
+ throw new Error ( `Expected quoted string, found "${ quoteChar } "` ) ;
111
+ }
112
+ i ++ ;
113
+
114
+ let entityValue = "" ;
115
+ while ( i < xmlData . length && xmlData [ i ] !== quoteChar ) {
116
+ entityValue += xmlData [ i ] ;
117
+ i ++ ;
118
+ }
119
+
120
+ if ( xmlData [ i ] !== quoteChar ) {
121
+ throw new Error ( "Unterminated entity value" ) ;
122
+ }
123
+
124
+ return [ entityName , entityValue , i ] ;
92
125
}
93
126
127
+
94
128
function isComment ( xmlData , i ) {
95
129
if ( xmlData [ i + 1 ] === '!' &&
96
130
xmlData [ i + 2 ] === '-' &&
0 commit comments