From 95c574eadcb9007567864b35888b0524b4e88f9b Mon Sep 17 00:00:00 2001 From: Yuya Ochiai Date: Thu, 27 Apr 2017 22:45:32 +0900 Subject: [PATCH 1/3] Show only save file dialog when clicking public file link For #390 --- src/browser/components/MattermostView.jsx | 9 +++- src/main.js | 9 ++++ src/main/downloadURL.js | 52 +++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/main/downloadURL.js 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; From 4c30d23ce96f6caca37efd9bf9c12b191510b207 Mon Sep 17 00:00:00 2001 From: Yuya Ochiai Date: Thu, 27 Apr 2017 23:33:20 +0900 Subject: [PATCH 2/3] Show error message box when failed to save file For #390 --- src/main.js | 4 ++++ src/main/downloadURL.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.js b/src/main.js index ed382254..61d3d699 100644 --- a/src/main.js +++ b/src/main.js @@ -327,6 +327,10 @@ allowProtocolDialog.init(mainWindow); ipcMain.on('download-url', (event, URL) => { downloadURL(mainWindow, URL, (err) => { if (err) { + dialog.showMessageBox(mainWindow, { + type: 'error', + message: err.toString() + }); console.log(err); } }); diff --git a/src/main/downloadURL.js b/src/main/downloadURL.js index a134a771..0d1187f2 100644 --- a/src/main/downloadURL.js +++ b/src/main/downloadURL.js @@ -35,7 +35,7 @@ function getAttachmentName(headers) { function saveResponseBody(response, filename, callback) { const output = fs.createWriteStream(filename); - output.on('close', callback).on('error', callback); + output.on('close', callback); switch (response.headers['content-encoding']) { case 'gzip': response.pipe(zlib.createGunzip()).pipe(output).on('error', callback); From 008a96f81c2da6fee8dc62fe590e0ea41766cbb2 Mon Sep 17 00:00:00 2001 From: Yuya Ochiai Date: Fri, 28 Apr 2017 00:04:23 +0900 Subject: [PATCH 3/3] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a89676e..d610a797 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ Release date: TBD #### All Platforms - Fixed an issue where an unexpected row appeared after switching channels with `CTRL+K` shortcut. [#426](https://github.com/mattermost/desktop/issues/426) +- Fixed an issue where an unexpected extra window opened when clicking the public link for an uploaded file. + [#390](https://github.com/mattermost/desktop/issues/390) #### Windows - Fixed an issue where the main window still has focus and exists