Skip to content

Commit 37f0ae4

Browse files
authored
check for content-dispostion in responses (#5065)
check for content-dispostion in responses.
1 parent 80c9b11 commit 37f0ae4

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

apps/dashboard/app/javascript/files/data_table.js

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,19 @@ class DataTable {
263263
this.updateGlobus();
264264
}
265265

266+
cleanHtml(html) {
267+
const parser = new DOMParser();
268+
const ele = parser.parseFromString(html, 'text/html');
269+
270+
const imgs = ele.querySelectorAll('img');
271+
imgs.forEach(img => { img.parentElement.removeChild(img) });
272+
273+
const scripts = ele.querySelectorAll('script');
274+
scripts.forEach(script => { script.parentElement.removeChild(script) });
275+
276+
return ele.body.innerHTML;
277+
}
278+
266279
async reloadTable(url) {
267280
var request_url = url || history.state.currentDirectoryUrl;
268281

@@ -272,7 +285,7 @@ class DataTable {
272285
const response = await fetch(request_url, { headers: { 'Accept': 'application/json' }, cache: 'no-store' });
273286
const data = await this.dataFromJsonResponse(response);
274287
history.state.currentFilenames = Array.from(data.files, x => x.name);
275-
$('#shell-wrapper').replaceWith((data.shell_dropdown_html));
288+
$('#shell-wrapper').replaceWith(this.cleanHtml(data.shell_dropdown_html));
276289

277290
this._table.clear();
278291
this._table.rows.add(data.files);
@@ -358,6 +371,14 @@ class DataTable {
358371
return new Promise((resolve, reject) => {
359372
Promise.resolve(response)
360373
.then(response => response.ok ? Promise.resolve(response) : Promise.reject(new Error(response.statusText)))
374+
.then(response => {
375+
const disposition = response.headers.get('content-disposition');
376+
if(disposition === null) {
377+
return response;
378+
} else {
379+
throw new Error("Cannot navigate to a file.");
380+
}
381+
})
361382
.then(response => response.json())
362383
.then(data => data.error_message ? Promise.reject(new Error(data.error_message)) : resolve(data))
363384
.catch((e) => reject(e))
@@ -367,7 +388,7 @@ class DataTable {
367388
renderNameColumn(data, type, row, meta) {
368389
let element = undefined;
369390

370-
if(!downloadEnabled() || row.url === undefined) {
391+
if(!downloadEnabled() || row.url === undefined || this.isInvalidURL(row.url)) {
371392
element = document.createElement('span');
372393
} else {
373394
element = document.createElement('a');
@@ -382,6 +403,16 @@ class DataTable {
382403
return element.outerHTML;
383404
}
384405

406+
isInvalidURL(urlString) {
407+
try {
408+
const url = new URL(urlString, window.location.origin);
409+
const protocol = url.protocol;
410+
return protocol === "javascript:" || protocol === "data:" || protocol === "vbscript:";
411+
} catch (error) {
412+
return true;
413+
}
414+
}
415+
385416
actionsBtnTemplate(options) {
386417
// options: { row_index: meta.row,
387418
// file: row.type != 'd',
@@ -501,7 +532,7 @@ class DataTable {
501532
this.reloadTable(url)
502533
.then((data) => {
503534
if(data) {
504-
$('#path-breadcrumbs').html(data.breadcrumbs_html);
535+
$('#path-breadcrumbs').html(this.cleanHtml(data.breadcrumbs_html));
505536
if(pushState) {
506537
// Clear search query when moving to another directory.
507538
this._table.search('').draw();

0 commit comments

Comments
 (0)