@@ -23,6 +23,8 @@ const COMPRESS_METHODS = ',gzip,brotli,zstd'.split(',');
2323const GZIP_OPTIONS = { level : 9 } ;
2424const HAS_BROTLI = zlib . createBrotliCompress != null ;
2525const HAS_ZSTD = zlib . createZstdCompress != null ;
26+ const HTML_ESCAPE_REG = / [ & < > " ] / g;
27+ const HTML_ESCAPE_TEST_REG = / [ & < > " ] / ;
2628const HTTP_LIST_REG = / , \s * / ;
2729const IMPORT_REG = / \b i m p o r t \( / g;
2830const IPS_PRIVATE = / ^ ( 1 2 7 \. | 1 0 \. | 1 9 2 \. 1 6 8 \. | : : 1 | f c 0 0 : | f e 8 0 : ) / ;
@@ -148,6 +150,13 @@ const rtjscomp = global.rtjscomp = {
148150 actions,
149151 version : VERSION ,
150152} ;
153+ const escape_html_char = char => (
154+ char === '&' ? '&' :
155+ char === '<' ? '<' :
156+ char === '>' ? '>' :
157+ char === '"' ? '"' :
158+ char
159+ ) ;
151160
152161// polyfills
153162if ( ! Object . fromEntries ) {
@@ -158,29 +167,6 @@ if (!Object.fromEntries) {
158167 }
159168}
160169
161- // legacy, will be removed soon!
162- global . globals = rtjscomp ;
163- global . actions = rtjscomp . actions ;
164- global . data_load = name => {
165- log ( '[deprecated] synchronous load file: ' + PATH_DATA + name ) ;
166- try {
167- return fs . readFileSync ( PATH_DATA + name , 'utf8' ) ;
168- }
169- catch ( err ) {
170- return null ;
171- }
172- }
173- global . data_save = ( name , data ) => (
174- log ( '[deprecated] synchronous save file: ' + PATH_DATA + name ) ,
175- fs . writeFileSync ( PATH_DATA + name , data , 'utf8' )
176- )
177- global . number_check_int = number => (
178- Math . floor ( number ) === number
179- )
180- global . number_check_uint = number => (
181- number >= 0 && number_check_int ( number )
182- )
183-
184170rtjscomp . data_load = async name => {
185171 if ( log_verbose ) log ( 'load file: ' + PATH_DATA + name ) ;
186172 const data = await fsp . readFile ( PATH_DATA + name , 'utf8' ) . catch ( ( ) => null ) ;
@@ -211,6 +197,11 @@ rtjscomp.data_save = (name, data) => (
211197 'utf8'
212198 )
213199)
200+ rtjscomp . escape_html = str => (
201+ HTML_ESCAPE_TEST_REG . test ( str )
202+ ? str . replace ( HTML_ESCAPE_REG , escape_html_char )
203+ : str
204+ ) ;
214205
215206/**
216207 hack to guess the line number of an error
@@ -1182,7 +1173,7 @@ const request_handle = async (request, response, https) => {
11821173
11831174 let code = `const log=a=>rtjscomp.log(${
11841175 JSON . stringify ( path + ': ' )
1185- } +a);`;
1176+ } +a),escape_html=rtjscomp.escape_html ;`;
11861177
11871178 let section_dynamic = false ;
11881179 let index_start = 0 ;
@@ -1202,28 +1193,28 @@ const request_handle = async (request, response, https) => {
12021193 section_dynamic = false ;
12031194 // section not empty?
12041195 if ( index_start < index_end ) {
1205- // `<?`?
1206- if ( file_content . charCodeAt ( index_start ) !== 61 ) {
1207- code += (
1208- file_content
1209- . slice (
1210- index_start ,
1211- index_end
1212- )
1213- . replace ( IMPORT_REG , 'custom_import(' ) +
1214- ';'
1215- ) ;
1196+ let before = '' ;
1197+ let after = ';' ;
1198+ const first_char = file_content . charCodeAt ( index_start ) ;
1199+ if ( first_char === 58 ) { // `<?:`?
1200+ ++ index_start ;
1201+ before = 'output.write(escape_html(""+(' ;
1202+ after = ')));' ;
12161203 }
1217- else { // `<?=`?
1218- code += `output.write(''+(${
1219- file_content
1220- . slice (
1221- ++ index_start ,
1222- index_end
1223- )
1224- . replace ( IMPORT_REG , 'custom_import(' )
1225- } ));`;
1204+ else if ( first_char === 61 ) { // `<?=`?
1205+ ++ index_start ;
1206+ before = 'output.write(""+(' ;
1207+ after = '));' ;
12261208 }
1209+
1210+ code += before + (
1211+ file_content
1212+ . slice (
1213+ index_start ,
1214+ index_end
1215+ )
1216+ . replace ( IMPORT_REG , 'custom_import(' )
1217+ ) + after ;
12271218 }
12281219 // skip `?>`
12291220 index_end += 2 ;
0 commit comments