diff --git a/src/browser/components/MattermostView.jsx b/src/browser/components/MattermostView.jsx index 85c43424..ecb39c40 100644 --- a/src/browser/components/MattermostView.jsx +++ b/src/browser/components/MattermostView.jsx @@ -64,9 +64,14 @@ const MattermostView = React.createClass({ ipcRenderer.send('confirm-protocol', destURL.protocol, e.url); return; } + if (currentURL.host === destURL.host) { - // New window should disable nodeIntergration. - window.open(e.url, 'Mattermost', 'nodeIntegration=no, show=yes'); + if (destURL.path.match(/^\/api\/v[3-4]\/public\/files\//)) { + ipcRenderer.send('download-url', e.url); + } else { + // New window should disable nodeIntergration. + window.open(e.url, 'Mattermost', 'nodeIntegration=no, show=yes'); + } } else { // if the link is external, use default browser. shell.openExternal(e.url); diff --git a/src/main.js b/src/main.js index d0f4a644..ed382254 100644 --- a/src/main.js +++ b/src/main.js @@ -61,6 +61,7 @@ var certificateStore = require('./main/certificateStore').load(path.resolve(app. const {createMainWindow} = require('./main/mainWindow'); const appMenu = require('./main/menus/app'); const trayMenu = require('./main/menus/tray'); +const downloadURL = require('./main/downloadURL'); const allowProtocolDialog = require('./main/allowProtocolDialog'); const assetsDir = path.resolve(app.getAppPath(), 'assets'); @@ -323,6 +324,14 @@ app.on('login', (event, webContents, request, authInfo, callback) => { allowProtocolDialog.init(mainWindow); +ipcMain.on('download-url', (event, URL) => { + downloadURL(mainWindow, URL, (err) => { + if (err) { + console.log(err); + } + }); +}); + // This method will be called when Electron has finished // initialization and is ready to create browser windows. app.on('ready', () => { diff --git a/src/main/downloadURL.js b/src/main/downloadURL.js new file mode 100644 index 00000000..a134a771 --- /dev/null +++ b/src/main/downloadURL.js @@ -0,0 +1,52 @@ +const fs = require('fs'); +const path = require('path'); +const zlib = require('zlib'); +const electron = require('electron'); +const {app, dialog} = electron; + +function downloadURL(browserWindow, URL, callback) { + const {net} = electron; + const request = net.request(URL); + request.setHeader('Accept-Encoding', 'gzip,deflate'); + request.on('response', (response) => { + const file = getAttachmentName(response.headers); + const dialogOptions = { + defaultPath: path.join(app.getPath('downloads'), file) + }; + dialog.showSaveDialog(browserWindow, dialogOptions, (filename) => { + if (filename) { + saveResponseBody(response, filename, callback); + } + }); + }).on('error', callback); + request.end(); +} + +function getAttachmentName(headers) { + if (headers['content-disposition']) { + const contentDisposition = headers['content-disposition'][0]; + const matched = contentDisposition.match(/filename="(.*)"/); + if (matched) { + return path.basename(matched[1]); + } + } + return ''; +} + +function saveResponseBody(response, filename, callback) { + const output = fs.createWriteStream(filename); + output.on('close', callback).on('error', callback); + switch (response.headers['content-encoding']) { + case 'gzip': + response.pipe(zlib.createGunzip()).pipe(output).on('error', callback); + break; + case 'deflate': + response.pipe(zlib.createInflate()).pipe(output).on('error', callback); + break; + default: + response.pipe(output).on('error', callback); + break; + } +} + +module.exports = downloadURL;