From dfe4273baf05da8c5d61a9fac572549287fdfb33 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 2 Oct 2020 13:17:53 -0700 Subject: [PATCH] Added Webkit download bug workaround. --- meshdevicefile.js | 4 +-- redirserver.js | 2 +- views/default.handlebars | 67 +++++++++++++++++++++++--------------- webserver.js | 70 ++++++++++++++++++++-------------------- 4 files changed, 79 insertions(+), 64 deletions(-) diff --git a/meshdevicefile.js b/meshdevicefile.js index 75dc1f6a..6950917e 100644 --- a/meshdevicefile.js +++ b/meshdevicefile.js @@ -204,9 +204,9 @@ module.exports.CreateMeshDeviceFile = function (parent, ws, res, req, domain, us if ((cmd == null) || (typeof cmd.op == 'string')) { if (cmd.op == 'ok') { if (typeof cmd.size == 'number') { - this.res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + require('path').basename(this.file) + '"', 'Content-Length': cmd.size }); + this.res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + require('path').basename(this.file) + '"', 'Content-Length': cmd.size }); } else { - this.res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + require('path').basename(this.file) + '"' }); + this.res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + require('path').basename(this.file) + '"' }); } } else { try { this.res.sendStatus(401); } catch (ex) { } diff --git a/redirserver.js b/redirserver.js index b67100e1..75226e28 100644 --- a/redirserver.js +++ b/redirserver.js @@ -53,7 +53,7 @@ module.exports.CreateRedirServer = function (parent, db, args, func) { obj.app.get('/MeshServerRootCert.cer', function (req, res) { // The redirection server starts before certificates are loaded, make sure to handle the case where no certificate is loaded now. if (obj.certificates != null) { - res.set({ 'Cache-Control': "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0", "Content-Type": "application/octet-stream", "Content-Disposition": "attachment; filename=\"" + obj.certificates.RootName + ".cer\"" }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + obj.certificates.RootName + '.cer"' }); var rootcert = obj.certificates.root.cert; var i = rootcert.indexOf('-----BEGIN CERTIFICATE-----\r\n'); if (i >= 0) { rootcert = rootcert.substring(i + 29); } diff --git a/views/default.handlebars b/views/default.handlebars index f913055b..2aed4867 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -1212,6 +1212,7 @@
+ - + \ No newline at end of file diff --git a/webserver.js b/webserver.js index 6b623b6d..986ff417 100644 --- a/webserver.js +++ b/webserver.js @@ -675,7 +675,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (domain.auth == 'sspi') { parent.debug('web', 'handleLogoutRequest: failed checks.'); res.sendStatus(404); return; } if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); // Destroy the user's session to log them out will be re-created next request if (req.session.userid) { var user = obj.users[req.session.userid]; @@ -2134,7 +2134,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { function handleRootRequestEx(req, res, domain, direct) { var nologout = false, user = null, features = 0; - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); // Check if we have an incomplete domain name in the path if ((domain.id != '') && (domain.dns == null) && (req.url.split('/').length == 2)) { @@ -2557,7 +2557,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key parent.debug('web', 'handleXTermRequest: sending xterm'); - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); if (req.session && req.session.userid) { if (req.session.domainid != domain.id) { res.redirect(domain.url + getQueryPortion(req)); return; } // Check if the session is for the correct domain var user = obj.users[req.session.userid]; @@ -2592,7 +2592,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // See if term.txt was loaded from the database if ((parent.configurationFiles != null) && (parent.configurationFiles['terms.txt'] != null)) { // Send the terms from the database - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); if (req.session && req.session.userid) { if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check if the session is for the correct domain var user = obj.users[req.session.userid]; @@ -2611,7 +2611,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (err != null) { parent.debug('web', 'handleTermsRequest: no terms.txt'); res.sendStatus(404); return; } // Send the terms from terms.txt - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); if (req.session && req.session.userid) { if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check if the session is for the correct domain var user = obj.users[req.session.userid]; @@ -2626,7 +2626,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } else { // Send the default terms parent.debug('web', 'handleTermsRequest: sending default terms'); - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); if (req.session && req.session.userid) { if (req.session.domainid != domain.id) { req.session = null; res.redirect(domain.url + getQueryPortion(req)); return; } // Check if the session is for the correct domain var user = obj.users[req.session.userid]; @@ -2649,7 +2649,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var webRtcConfig = null; if (obj.parent.config.settings && obj.parent.config.settings.webrtconfig && (typeof obj.parent.config.settings.webrtconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(obj.parent.config.settings.webrtconfig)).replace(/'/g, '%27'); } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); render(req, res, getRenderPage('messenger', req, domain), getRenderArgs({ webrtconfig: webRtcConfig }, req, domain)); } @@ -2671,9 +2671,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false)) { parent.debug('web', 'handleRootCertRequest: invalid ip'); return; } // Check server-wide IP filter only. parent.debug('web', 'handleRootCertRequest()'); try { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + certificates.RootName + '.cer"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + certificates.RootName + '.cer"' }); } catch (ex) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="rootcert.cer"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="rootcert.cer"' }); } res.send(Buffer.from(getRootCertBase64(), 'base64')); } @@ -2779,9 +2779,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (script == null) { res.sendStatus(404); } else { try { var cirafilename = obj.meshes[req.query.meshid].name.split('\\').join('').split('/').join('').split(':').join('').split('*').join('').split('?').join('').split('"').join('').split('<').join('').split('>').join('').split('|').join('').split(' ').join('').split('\'').join(''); - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="cira_setup_' + cirafilename + '.mescript"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="cira_setup_' + cirafilename + '.mescript"' }); } catch (ex) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="cira_setup.mescript"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="cira_setup.mescript"' }); } res.send(script); } @@ -2790,7 +2790,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Get the CIRA cleanup script obj.getCiraCleanupScript(function (script) { if (script == null) { res.sendStatus(404); } else { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="cira_cleanup.mescript"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="cira_cleanup.mescript"' }); res.send(script); } }); @@ -2817,9 +2817,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((stat != null) && ((stat.mode & 0x004000) == 0)) { if (req.query.download == 1) { try { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + filename + '\"' }); } catch (ex) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"file.bin\"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"file.bin\"' }); } try { res.sendFile(obj.path.resolve(__dirname, path)); } catch (e) { res.sendStatus(404); } } else { @@ -3035,7 +3035,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((user.siteadmin & 512) == 0) { res.sendStatus(401); return; } // Check if we have right to get recordings // Send the recorded file - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + req.query.file + '\"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + req.query.file + '\"' }); try { res.sendFile(obj.path.join(recordingsPath, req.query.file)); } catch (ex) { res.sendStatus(404); } } @@ -3045,7 +3045,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (domain == null) { return; } parent.debug('web', 'handlePlayerRequest: sending player'); - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); render(req, res, getRenderPage('player', req, domain), getRenderArgs({}, req, domain)); } @@ -3066,7 +3066,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Lets respond by sending out the desktop viewer. var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified parent.debug('web', 'handleDesktopRequest: Sending guest desktop page for \"' + c.uid + '\", guest \"' + c.gn + '\".'); - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.set({ 'Cache-Control': 'no-store' }); render(req, res, getRenderPage('desktop', req, domain), getRenderArgs({ authCookie: authCookie, authRelayCookie: '', domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), nodeid: c.nid, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, expire: c.expire }, req, domain)); } @@ -3131,9 +3131,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { const file = obj.getServerFilePath(user, domain, req.query.link); if (file == null) { res.sendStatus(404); return; } try { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + file.name + '\"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"' + file.name + '\"' }); } catch (ex) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"file.bin\"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=\"file.bin\"' }); } obj.fs.exists(file.fullpath, function (exists) { if (exists == true) { res.sendFile(file.fullpath); } else { res.sendStatus(404); } }); } @@ -4144,7 +4144,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { for (var i in meshsettingslines) { tokens = meshsettingslines[i].split('='); if (tokens.length == 2) { msh[tokens[0]] = tokens[1]; } } var js = scriptInfo.data.replace('var msh = {};', 'var msh = ' + JSON.stringify(msh) + ';'); - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshagent"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshagent"' }); res.statusCode = 200; obj.parent.exeHandler.streamExeWithJavaScript({ platform: argentInfo.platform, sourceFileName: argentInfo.path, destinationStream: res, js: Buffer.from(js, 'utf8'), peinfo: argentInfo.pe }); } else if (req.query.id != null) { @@ -4152,7 +4152,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var argentInfo = obj.parent.meshAgentBinaries[req.query.id]; if (argentInfo == null) { res.sendStatus(404); return; } if ((req.query.meshid == null) || (argentInfo.platform != 'win32')) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + argentInfo.rname + '"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + argentInfo.rname + '"' }); if (argentInfo.data == null) { res.sendFile(argentInfo.path); } else { res.end(argentInfo.data); } } else { // Check if the meshid is a time limited, encrypted cookie @@ -4199,9 +4199,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (domain.agentconfig) { for (var i in domain.agentconfig) { meshsettings += domain.agentconfig[i] + '\r\n'; } } try { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + meshfilename + '"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + meshfilename + '"' }); } catch (ex) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + argentInfo.rname + '"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + argentInfo.rname + '"' }); } obj.parent.exeHandler.streamExeWithMeshPolicy({ platform: 'win32', sourceFileName: obj.parent.meshAgentBinaries[req.query.id].path, destinationStream: res, msh: meshsettings, peinfo: obj.parent.meshAgentBinaries[req.query.id].pe }); } @@ -4211,7 +4211,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Send a specific mesh install script back var scriptInfo = obj.parent.meshAgentInstallScripts[req.query.script]; if (scriptInfo == null) { res.sendStatus(404); return; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="' + scriptInfo.rname + '"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="' + scriptInfo.rname + '"' }); var data = scriptInfo.data; var cmdoptions = { wgetoptionshttp: '', wgetoptionshttps: '', curloptionshttp: '-L ', curloptionshttps: '-L ' } if (obj.isTrustedCert(domain) != true) { @@ -4235,17 +4235,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((agentid == 3)) { // Signed Windows MeshCmd.exe x86 var stats = null, meshCmdPath = obj.path.join(__dirname, 'agents', 'MeshCmd-signed.exe'); try { stats = obj.fs.statSync(meshCmdPath); } catch (e) { } - if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 3) ? '.exe' : '') + '"' }); res.sendFile(meshCmdPath); return; } + if ((stats != null)) { res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 3) ? '.exe' : '') + '"' }); res.sendFile(meshCmdPath); return; } } else if ((agentid == 4)) { // Signed Windows MeshCmd64.exe x64 var stats = null, meshCmd64Path = obj.path.join(__dirname, 'agents', 'MeshCmd64-signed.exe'); try { stats = obj.fs.statSync(meshCmd64Path); } catch (e) { } - if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') + '"' }); res.sendFile(meshCmd64Path); return; } + if ((stats != null)) { res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') + '"' }); res.sendFile(meshCmd64Path); return; } } // No signed agents, we are going to merge a new MeshCmd. if ((agentid < 10000) && (obj.parent.meshAgentBinaries[agentid + 10000] != null)) { agentid += 10000; } // Avoid merging javascript to a signed mesh agent. var argentInfo = obj.parent.meshAgentBinaries[agentid]; if ((argentInfo == null) || (obj.parent.defaultMeshCmd == null)) { res.sendStatus(404); return; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') + '"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') + '"' }); res.statusCode = 200; if (argentInfo.signedMeshCmdPath != null) { // If we have a pre-signed MeshCmd, send that. @@ -4281,7 +4281,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (req.query.key != null) { meshaction.loginKey = req.query.key; } var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="meshaction.txt"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="meshaction.txt"' }); res.send(JSON.stringify(meshaction, null, ' ')); }); } else if (req.query.meshaction == 'generic') { @@ -4296,12 +4296,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (req.query.key != null) { meshaction.loginKey = req.query.key; } var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="meshaction.txt"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="meshaction.txt"' }); res.send(JSON.stringify(meshaction, null, ' ')); } else if (req.query.meshaction == 'winrouter') { var p = obj.path.join(__dirname, 'agents', 'MeshCentralRouter.exe'); if (obj.fs.existsSync(p)) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="MeshCentralRouter.exe"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="MeshCentralRouter.exe"' }); try { res.sendFile(p); } catch (e) { res.sendStatus(404); } } else { res.sendStatus(404); } } else { @@ -4324,7 +4324,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Download a dump file var dumpFile = obj.path.join(parent.datapath, '..', 'meshcentral-coredumps', req.query.dldump); if (obj.fs.existsSync(dumpFile)) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="' + req.query.dldump + '' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="' + req.query.dldump + '' }); res.sendFile(dumpFile); return; } else { res.sendStatus(404); return; @@ -4464,10 +4464,10 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { archive.on('error', function (err) { throw err; }); try { // Set the agent download including the mesh name. - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="MeshAgent-' + mesh.name + '.zip"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="MeshAgent-' + mesh.name + '.zip"' }); } catch (ex) { // If the mesh name contains invalid characters, just use a generic name. - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="MeshAgent.zip"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="MeshAgent.zip"' }); } archive.pipe(res); @@ -4566,7 +4566,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var meshsettings = getMshFromRequest(req, res, domain); if (meshsettings == null) { res.sendStatus(401); return; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshagent.msh"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshagent.msh"' }); res.send(meshsettings); }; @@ -4590,7 +4590,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (obj.GetNodeRights(user, node.meshid, node._id) == 0) { res.sendStatus(401); return; } // Get the list of power events and send them - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="powerevents.csv"' }); + res.set({ 'Cache-Control': 'no-store', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="powerevents.csv"' }); obj.db.getPowerTimeline(node._id, function (err, docs) { var xevents = ['Time, State, Previous State'], prevState = 0; for (var i in docs) {