diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index 6bea75501c1c..5d173ffbd0de 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 1.3.1 +ENV RC_VERSION 1.3.2 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 369d03f3975c..c916720042ec 100644 --- a/.github/history.json +++ b/.github/history.json @@ -33563,6 +33563,66 @@ ] } ] + }, + "1.3.2": { + "node_version": "8.11.4", + "npm_version": "6.4.1", + "mongo_versions": [ + "3.2", + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "15172", + "title": "[FIX] Attachment download button behavior", + "userLogin": "tassoevan", + "milestone": "1.3.2", + "contributors": [ + "tassoevan", + "sampaiodiego" + ] + }, + { + "pr": "15175", + "title": "[FIX] Messages search scroll", + "userLogin": "ggazzo", + "milestone": "1.3.2", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "15157", + "title": "[FIX] IE11 - callback createTreeWalker doesnt accept acceptNode", + "userLogin": "ggazzo", + "milestone": "1.3.2", + "contributors": [ + "ggazzo", + "tassoevan" + ] + }, + { + "pr": "15173", + "title": "Update latest Livechat widget version to 1.1.4", + "userLogin": "renatobecker", + "milestone": "1.3.2", + "contributors": [ + "renatobecker" + ] + }, + { + "pr": "15154", + "title": "Update latest Livechat widget version(1.1.3)", + "userLogin": "renatobecker", + "milestone": "1.3.2", + "contributors": [ + "renatobecker", + "web-flow" + ] + } + ] } } } \ No newline at end of file diff --git a/.travis/snap.sh b/.travis/snap.sh index a3d692f673f9..83a17c0fcf81 100755 --- a/.travis/snap.sh +++ b/.travis/snap.sh @@ -17,7 +17,7 @@ elif [[ $TRAVIS_TAG ]]; then RC_VERSION=$TRAVIS_TAG else CHANNEL=edge - RC_VERSION=1.3.1 + RC_VERSION=1.3.2 fi echo "Preparing to trigger a snap release for $CHANNEL channel" diff --git a/HISTORY.md b/HISTORY.md index c1281fd07ba9..f3e0e8af972e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,6 @@ -# 1.3.1 -`2019-08-08 · 2 🐛 · 2 👩‍💻👨‍💻` +# 1.3.2 +`2019-08-13 · 3 🐛 · 2 🔍 · 4 👩‍💻👨‍💻` ### Engine versions - Node: `8.11.4` @@ -9,21 +9,42 @@ ### 🐛 Bug fixes -- Custom emoji table scroll ([#15119](https://github.com/RocketChat/Rocket.Chat/pull/15119)) -- Direct Message names not visible on Admin panel ([#15114](https://github.com/RocketChat/Rocket.Chat/pull/15114)) +- Attachment download button behavior ([#15172](https://github.com/RocketChat/Rocket.Chat/pull/15172)) +- Messages search scroll ([#15175](https://github.com/RocketChat/Rocket.Chat/pull/15175)) +- IE11 - callback createTreeWalker doesnt accept acceptNode ([#15157](https://github.com/RocketChat/Rocket.Chat/pull/15157))
🔍 Minor changes -- Fix custom auth ([#15141](https://github.com/RocketChat/Rocket.Chat/pull/15141)) +- Update latest Livechat widget version to 1.1.4 ([#15173](https://github.com/RocketChat/Rocket.Chat/pull/15173)) +- Update latest Livechat widget version(1.1.3) ([#15154](https://github.com/RocketChat/Rocket.Chat/pull/15154))
### 👩‍💻👨‍💻 Core Team 🤓 +- [@ggazzo](https://github.com/ggazzo) +- [@renatobecker](https://github.com/renatobecker) +- [@sampaiodiego](https://github.com/sampaiodiego) +- [@tassoevan](https://github.com/tassoevan) + +# 1.3.1 +`2019-08-08 · 2 🐛 · 2 👩‍💻👨‍💻` + +### Engine versions +- Node: `8.11.4` +- NPM: `6.4.1` +- MongoDB: `3.2, 3.4, 3.6, 4.0` + +### 🐛 Bug fixes + +- Custom emoji table scroll ([#15119](https://github.com/RocketChat/Rocket.Chat/pull/15119)) +- Direct Message names not visible on Admin panel ([#15114](https://github.com/RocketChat/Rocket.Chat/pull/15114)) + +### 👩‍💻👨‍💻 Core Team 🤓 + - [@ggazzo](https://github.com/ggazzo) - [@sampaiodiego](https://github.com/sampaiodiego) -- [@MarcosSpessatto](https://github.com/MarcosSpessatto) # 1.3.0 `2019-08-02 · 9 🎉 · 6 🚀 · 31 🐛 · 31 🔍 · 29 👩‍💻👨‍💻` @@ -5369,4 +5390,4 @@ - [@marceloschmidt](https://github.com/marceloschmidt) - [@mrsimpson](https://github.com/mrsimpson) - [@rodrigok](https://github.com/rodrigok) -- [@sampaiodiego](https://github.com/sampaiodiego) +- [@sampaiodiego](https://github.com/sampaiodiego) \ No newline at end of file diff --git a/app/emoji/client/emojiParser.js b/app/emoji/client/emojiParser.js index 00ef84402bee..d7f7980df11a 100644 --- a/app/emoji/client/emojiParser.js +++ b/app/emoji/client/emojiParser.js @@ -3,6 +3,7 @@ import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; import { getUserPreference } from '../../utils'; +import { isIE11 } from '../../ui-utils/client/lib/isIE11'; import { callbacks } from '../../callbacks'; import { emoji } from '../lib/rocketchat'; @@ -32,41 +33,44 @@ Tracker.autorun(() => { const emojis = Array.from(checkEmojiOnly.querySelectorAll('.emoji:not(:empty), .emojione:not(:empty)')); - const walker = document.createTreeWalker( - checkEmojiOnly, - NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, - { - acceptNode: (node) => { - if (node.nodeType === Node.ELEMENT_NODE && ( - node.classList.contains('emojione') - || node.classList.contains('emoji') - )) { - return NodeFilter.FILTER_REJECT; - } - return NodeFilter.FILTER_ACCEPT; - }, - }, - ); - let hasText = false; - while (walker.nextNode()) { - if (walker.currentNode.nodeType === Node.TEXT_NODE && walker.currentNode.nodeValue.trim() !== '') { - hasText = true; - break; + if (!isIE11()) { + const filter = (node) => { + if (node.nodeType === Node.ELEMENT_NODE && ( + node.classList.contains('emojione') + || node.classList.contains('emoji') + )) { + return NodeFilter.FILTER_REJECT; + } + return NodeFilter.FILTER_ACCEPT; + }; + + const walker = document.createTreeWalker( + checkEmojiOnly, + NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, + filter + ); + + + while (walker.nextNode()) { + if (walker.currentNode.nodeType === Node.TEXT_NODE && walker.currentNode.nodeValue.trim() !== '') { + hasText = true; + break; + } } - } - - const emojiOnly = emojis.length && !hasText; - - if (emojiOnly) { - for (let i = 0, len = emojis.length; i < len; i++) { - const { classList } = emojis[i]; - classList.add('big'); + const emojiOnly = emojis.length && !hasText; + + if (emojiOnly) { + for (let i = 0, len = emojis.length; i < len; i++) { + const { classList } = emojis[i]; + classList.add('big'); + } + html = checkEmojiOnly.innerHTML; } - html = checkEmojiOnly.innerHTML; } + // apostrophe (') back to ' html = html.replace(/\'/g, '''); diff --git a/app/file-upload/server/config/AmazonS3.js b/app/file-upload/server/config/AmazonS3.js index c262351fc0da..48aea6aea167 100644 --- a/app/file-upload/server/config/AmazonS3.js +++ b/app/file-upload/server/config/AmazonS3.js @@ -8,23 +8,21 @@ import { FileUploadClass, FileUpload } from '../lib/FileUpload'; import '../../ufs/AmazonS3/server.js'; const get = function(file, req, res) { - const fileUrl = this.store.getRedirectURL(file); + const forceDownload = typeof req.query.download !== 'undefined'; + const fileUrl = this.store.getRedirectURL(file, forceDownload); - if (fileUrl) { - const storeType = file.store.split(':').pop(); - if (settings.get(`FileUpload_S3_Proxy_${ storeType }`)) { - const request = /^https:/.test(fileUrl) ? https : http; - request.get(fileUrl, (fileRes) => fileRes.pipe(res)); - } else { - res.removeHeader('Content-Length'); - res.removeHeader('Cache-Control'); - res.setHeader('Location', fileUrl); - res.writeHead(302); - res.end(); - } - } else { - res.end(); + if (!fileUrl) { + return res.end(); + } + + const storeType = file.store.split(':').pop(); + if (settings.get(`FileUpload_S3_Proxy_${ storeType }`)) { + const request = /^https:/.test(fileUrl) ? https : http; + + return FileUpload.proxyFile(file.name, fileUrl, forceDownload, request, req, res); } + + return FileUpload.redirectToFile(fileUrl, req, res); }; const copy = function(file, out) { diff --git a/app/file-upload/server/config/GoogleStorage.js b/app/file-upload/server/config/GoogleStorage.js index 0af606ead1f0..c8e11bfe1fb5 100644 --- a/app/file-upload/server/config/GoogleStorage.js +++ b/app/file-upload/server/config/GoogleStorage.js @@ -8,31 +8,30 @@ import { settings } from '../../../settings'; import '../../ufs/GoogleStorage/server.js'; const get = function(file, req, res) { - this.store.getRedirectURL(file, (err, fileUrl) => { + const forceDownload = typeof req.query.download !== 'undefined'; + + this.store.getRedirectURL(file, forceDownload, (err, fileUrl) => { if (err) { - console.error(err); + return console.error(err); } - if (fileUrl) { - const storeType = file.store.split(':').pop(); - if (settings.get(`FileUpload_GoogleStorage_Proxy_${ storeType }`)) { - const request = /^https:/.test(fileUrl) ? https : http; - request.get(fileUrl, (fileRes) => fileRes.pipe(res)); - } else { - res.removeHeader('Content-Length'); - res.removeHeader('Cache-Control'); - res.setHeader('Location', fileUrl); - res.writeHead(302); - res.end(); - } - } else { - res.end(); + if (!fileUrl) { + return res.end(); } + + const storeType = file.store.split(':').pop(); + if (settings.get(`FileUpload_GoogleStorage_Proxy_${ storeType }`)) { + const request = /^https:/.test(fileUrl) ? https : http; + + return FileUpload.proxyFile(file.name, fileUrl, forceDownload, request, req, res); + } + + return FileUpload.redirectToFile(fileUrl, req, res); }); }; const copy = function(file, out) { - this.store.getRedirectURL(file, (err, fileUrl) => { + this.store.getRedirectURL(file, false, (err, fileUrl) => { if (err) { console.error(err); } diff --git a/app/file-upload/server/lib/FileUpload.js b/app/file-upload/server/lib/FileUpload.js index 9258da3fcd1e..aed9f1b41f82 100644 --- a/app/file-upload/server/lib/FileUpload.js +++ b/app/file-upload/server/lib/FileUpload.js @@ -371,6 +371,20 @@ export const FileUpload = { return false; }, + + redirectToFile(fileUrl, req, res) { + res.removeHeader('Content-Length'); + res.removeHeader('Cache-Control'); + res.setHeader('Location', fileUrl); + res.writeHead(302); + res.end(); + }, + + proxyFile(fileName, fileUrl, forceDownload, request, req, res) { + res.setHeader('Content-Disposition', `${ forceDownload ? 'attachment' : 'inline' }; filename="${ encodeURI(fileName) }"`); + + request.get(fileUrl, (fileRes) => fileRes.pipe(res)); + }, }; export class FileUploadClass { diff --git a/app/file-upload/ufs/AmazonS3/server.js b/app/file-upload/ufs/AmazonS3/server.js index 656bfb2c0656..a22014a73904 100644 --- a/app/file-upload/ufs/AmazonS3/server.js +++ b/app/file-upload/ufs/AmazonS3/server.js @@ -47,10 +47,11 @@ export class AmazonS3Store extends UploadFS.Store { } }; - this.getRedirectURL = function(file) { + this.getRedirectURL = function(file, forceDownload = false) { const params = { Key: this.getPath(file), Expires: classOptions.URLExpiryTimeSpan, + ResponseContentDisposition: `${ forceDownload ? 'attachment' : 'inline' }; filename="${ encodeURI(file.name) }"`, }; return s3.getSignedUrl('getObject', params); @@ -140,7 +141,6 @@ export class AmazonS3Store extends UploadFS.Store { Key: this.getPath(file), Body: writeStream, ContentType: file.type, - ContentDisposition: `inline; filename="${ encodeURI(file.name) }"`, }, (error) => { if (error) { diff --git a/app/file-upload/ufs/GoogleStorage/server.js b/app/file-upload/ufs/GoogleStorage/server.js index b350caa6df38..47b384466549 100644 --- a/app/file-upload/ufs/GoogleStorage/server.js +++ b/app/file-upload/ufs/GoogleStorage/server.js @@ -30,10 +30,10 @@ export class GoogleStorageStore extends UploadFS.Store { } }; - this.getRedirectURL = function(file, callback) { + this.getRedirectURL = function(file, forceDownload = false, callback) { const params = { action: 'read', - responseDisposition: 'inline', + responseDisposition: forceDownload ? 'attachment' : 'inline', expires: Date.now() + this.options.URLExpiryTimeSpan * 1000, }; diff --git a/app/markdown/lib/parser/original/markdown.js b/app/markdown/lib/parser/original/markdown.js index 09517cd6fd4e..e0817c542f38 100644 --- a/app/markdown/lib/parser/original/markdown.js +++ b/app/markdown/lib/parser/original/markdown.js @@ -23,7 +23,7 @@ const parseNotEscaped = function(msg, message) { return token; }; - const schemes = settings.get('Markdown_SupportSchemesForLink').split(',').join('|'); + const schemes = (settings.get('Markdown_SupportSchemesForLink') || '').split(',').join('|'); if (settings.get('Markdown_Headers')) { // Support # Text for h1 diff --git a/app/message-attachments/client/messageAttachment.html b/app/message-attachments/client/messageAttachment.html index d5165110ce89..03b3a606a4c8 100644 --- a/app/message-attachments/client/messageAttachment.html +++ b/app/message-attachments/client/messageAttachment.html @@ -57,7 +57,7 @@ {{#if title_link}} {{title}} {{#if title_link_download}} - {{> icon icon="download"}} + {{> icon icon="download"}} {{/if}} {{else}} {{title}} diff --git a/app/search/client/provider/result.js b/app/search/client/provider/result.js index 03367888e29c..1d62162bd202 100644 --- a/app/search/client/provider/result.js +++ b/app/search/client/provider/result.js @@ -46,7 +46,7 @@ Template.DefaultSearchResultTemplate.onRendered(function() { const result = this.data.result.get(); if (result && this.hasMore.get()) { Tracker.afterFlush(() => { - if (list.scrollHeight <= list.offsetHeight) { + if (list.scrollHeight < list.offsetHeight) { this.data.payload.limit = (this.data.payload.limit || this.pageSize) + this.pageSize; this.data.search(); } diff --git a/app/search/client/style/style.css b/app/search/client/style/style.css index 93e7c4aa8d00..cd7509548840 100644 --- a/app/search/client/style/style.css +++ b/app/search/client/style/style.css @@ -25,7 +25,7 @@ display: flex; overflow: hidden; flex-direction: column; - flex: 1; + flex: 1 1 0; } .rocket-default-search-settings { diff --git a/app/ui-utils/client/lib/isIE11.js b/app/ui-utils/client/lib/isIE11.js new file mode 100644 index 000000000000..c494c5c63202 --- /dev/null +++ b/app/ui-utils/client/lib/isIE11.js @@ -0,0 +1,15 @@ +export const isIE11 = () => { + const { userAgent } = window.navigator; + const msieIdx = userAgent.indexOf('MSIE'); + + if (msieIdx > 0) { + return parseInt(userAgent.substring(msieIdx + 5, userAgent.indexOf('.', msieIdx))) === 11; + } + + // If MSIE detection fails, check the Trident engine version + if (navigator.userAgent.match(/Trident\/7\./)) { + return true; + } + + return false; +}; diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 8a9436e88d3b..7ad34b9e2b96 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "1.3.1" + "version": "1.3.2" } diff --git a/imports/client/@rocket.chat/apps-engine b/imports/client/@rocket.chat/apps-engine new file mode 120000 index 000000000000..9a368c3d1407 --- /dev/null +++ b/imports/client/@rocket.chat/apps-engine @@ -0,0 +1 @@ +../../../node_modules/@rocket.chat/apps-engine \ No newline at end of file diff --git a/package.json b/package.json index aa24a8eb7c9b..30667a155038 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "1.3.1", + "version": "1.3.2", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" diff --git a/packages/rocketchat-livechat/plugin/build.sh b/packages/rocketchat-livechat/plugin/build.sh index 37d09b1db2a3..f5a8a02760fd 100644 --- a/packages/rocketchat-livechat/plugin/build.sh +++ b/packages/rocketchat-livechat/plugin/build.sh @@ -3,8 +3,7 @@ export LIVECHAT_DIR="../../../public/livechat" export BUILD_DIR="../build" export BUNDLE_DIR="../build/bundle/programs/web.browser.legacy" export LIVECHAT_ASSETS_DIR="../../../private/livechat" -export LATEST_LIVECHAT_VERSION="1.1.0" -export LIVECHAT_VERSION_DIR="1.0.0" +export LATEST_LIVECHAT_VERSION="1.1.4" cd packages/rocketchat-livechat/.app meteor npm install --production @@ -23,10 +22,8 @@ cp $BUNDLE_DIR/head.html $LIVECHAT_ASSETS_DIR/head.html rm -rf $BUILD_DIR #NEW LIVECHAT# -echo "Installing new Livechat..." +echo "Installing Livechat ${LATEST_LIVECHAT_VERSION}..." cd $LIVECHAT_DIR -mkdir -p $LIVECHAT_VERSION_DIR -cd $LIVECHAT_VERSION_DIR curl -sOL "https://github.com/RocketChat/Rocket.Chat.Livechat/releases/download/v${LATEST_LIVECHAT_VERSION}/build.tar.gz" tar -xf build.tar.gz @@ -36,5 +33,4 @@ rm build.tar.gz # this is not harmful since doctype is case-insesitive: https://www.w3.org/TR/html5/syntax.html#the-doctype node -e 'fs.writeFileSync("index.html", fs.readFileSync("index.html").toString().replace("