From 6682e048ea72aa1c5b25a56fc0eaf12a9d131c1b Mon Sep 17 00:00:00 2001 From: Aziz Khoury Date: Wed, 22 Mar 2017 12:19:31 +0200 Subject: [PATCH 1/6] wrapImagesInLinks with attribute if the `src` of the `img` does not have an extension, most browsers will trigger a download with whatever filename is set, also without an extension, so when it's opened in any OS, it wont have a default application to open it with. So, In this case, if the `alt` attribute has an extension (meaning if it looks like filename) - we use that with the html5 [`download` attr](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download) The PR does not affect any src if they have an extension. --- public/src/client/topic/images.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/public/src/client/topic/images.js b/public/src/client/topic/images.js index cd44dd0914..20981f6b80 100644 --- a/public/src/client/topic/images.js +++ b/public/src/client/topic/images.js @@ -97,19 +97,25 @@ define('forum/topic/images', [ Images.wrapImagesInLinks = function (posts) { posts.find('[component="post/content"] img:not(.emoji)').each(function () { var $this = $(this); - var src = $this.attr('src'); + var src = $this.attr('src') || ''; + var alt = $this.attr('alt') || ''; var suffixRegex = /-resized(\.[\w]+)?$/; if (src === 'about:blank') { return; } - + if (utils.isRelativeUrl(src) && suffixRegex.test(src)) { src = src.replace(suffixRegex, '$1'); } + var srcExt = src.split('.').slice(1).pop(); + var altFilename = alt.split('/').pop(); + var altExt = altFilename.split('.').slice(1).pop(); if (!$this.parent().is('a')) { - $this.wrap(''); + $this.wrap(''); } }); }; From 6060b8e13b37cf0457b1215b3f25275649914123 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Thu, 23 Mar 2017 14:39:46 -0400 Subject: [PATCH 2/6] fix tests --- public/src/client/topic/images.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/src/client/topic/images.js b/public/src/client/topic/images.js index 20981f6b80..52f0671a78 100644 --- a/public/src/client/topic/images.js +++ b/public/src/client/topic/images.js @@ -104,7 +104,7 @@ define('forum/topic/images', [ if (src === 'about:blank') { return; } - + if (utils.isRelativeUrl(src) && suffixRegex.test(src)) { src = src.replace(suffixRegex, '$1'); } @@ -114,8 +114,8 @@ define('forum/topic/images', [ if (!$this.parent().is('a')) { $this.wrap(''); + + (!srcExt && altExt ? ' download="' + altFilename + '" ' : '') + + ' target="_blank" >'); } }); }; From 3319a7267978fe7c4208dbac4afcc1c73d0d5659 Mon Sep 17 00:00:00 2001 From: "Misty (Bot)" Date: Fri, 24 Mar 2017 09:22:18 +0000 Subject: [PATCH 3/6] Latest translations and fallbacks --- public/language/pt-BR/admin/advanced/errors.json | 2 +- public/language/pt-BR/admin/general/dashboard.json | 14 +++++++------- public/language/pt-BR/admin/settings/general.json | 2 +- public/language/pt-BR/admin/settings/uploads.json | 2 +- public/language/pt-BR/notifications.json | 6 +++--- public/language/pt-BR/pages.json | 6 +++--- public/language/pt-BR/search.json | 2 +- public/language/pt-BR/topic.json | 4 ++-- public/language/pt-BR/user.json | 6 +++--- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/public/language/pt-BR/admin/advanced/errors.json b/public/language/pt-BR/admin/advanced/errors.json index 67ac477f0a..90c85005fa 100644 --- a/public/language/pt-BR/admin/advanced/errors.json +++ b/public/language/pt-BR/admin/advanced/errors.json @@ -8,7 +8,7 @@ "clear-error-log": "Limpar Log de Erros", "route": "Rota", "count": "Contagem", - "no-routes-not-found": "Hooray! No 404 errors!", + "no-routes-not-found": "Ihuul! Sem erros 404!", "clear404-confirm": "Você tem certeza que deseja limpar todos os logs de erro 404?", "clear404-success": "Erros de \"404 Não Encontrada\" apagados" } \ No newline at end of file diff --git a/public/language/pt-BR/admin/general/dashboard.json b/public/language/pt-BR/admin/general/dashboard.json index d818f5f754..d1a7be1c77 100644 --- a/public/language/pt-BR/admin/general/dashboard.json +++ b/public/language/pt-BR/admin/general/dashboard.json @@ -2,9 +2,9 @@ "forum-traffic": "Tráfego do Forum", "page-views": "Visualizações de Página", "unique-visitors": "Visitantes Únicos", - "users": "Users", + "users": "Usuários", "posts": "Posts", - "topics": "Topics", + "topics": "Tópicos", "page-views-last-month": "Visualizações de página no Último Mês", "page-views-this-month": "Visualizações de Página Este Mês", "page-views-last-day": "Visualizações de página nas últimas 24 horas", @@ -23,11 +23,11 @@ "prerelease-warning": "

Esta é uma versão pre-release do NodeBB. Bugs inesperados podem ocorrer.

", "notices": "Avisos", - "restart-not-required": "Restart not required", - "restart-required": "Restart required", - "search-plugin-installed": "Search Plugin installed", - "search-plugin-not-installed": "Search Plugin not installed", - "search-plugin-tooltip": "Install a search plugin from the plugin page in order to activate search functionality", + "restart-not-required": "Reiniciar não é necessário", + "restart-required": "É necessário reiniciar", + "search-plugin-installed": "Plugin de Pesquisa instalado", + "search-plugin-not-installed": "Plugin de Pesquisa não instalado", + "search-plugin-tooltip": "Instale um plugin de pesquisa da página de plugins de modo à ativar a funcionalidade de pesquisa", "control-panel": "Controle do Sistema", "reload": "Recarregar", diff --git a/public/language/pt-BR/admin/settings/general.json b/public/language/pt-BR/admin/settings/general.json index 82ac4fb667..3326dcb8ec 100644 --- a/public/language/pt-BR/admin/settings/general.json +++ b/public/language/pt-BR/admin/settings/general.json @@ -27,5 +27,5 @@ "touch-icon.help": "Tamanho e formato recomendados: 192x192, apenas formato PNG. Se nenhum ícone de touch screen for especificado, o NodeBB usará o seu favicon, ao invés dele.", "outgoing-links": "Links Externos", "outgoing-links.warning-page": "Utilizar Página de Aviso de Links Externos", - "search-default-sort-by": "Search default sort by" + "search-default-sort-by": "Padrão de ordenação de pesquisa por" } \ No newline at end of file diff --git a/public/language/pt-BR/admin/settings/uploads.json b/public/language/pt-BR/admin/settings/uploads.json index 8016a20720..2a020becb5 100644 --- a/public/language/pt-BR/admin/settings/uploads.json +++ b/public/language/pt-BR/admin/settings/uploads.json @@ -9,7 +9,7 @@ "allow-topic-thumbnails": "Permitir usuários de enviar miniaturas de tópico", "topic-thumb-size": "Tamanho da Miniatura de Tópico", "allowed-file-extensions": "Extensões de Arquivo Permitidas", - "allowed-file-extensions-help": "Enter comma-separated list of file extensions here (e.g. pdf,xls,doc). An empty list means all extensions are allowed.", + "allowed-file-extensions-help": "Digite uma lista separada por vírguls fr extensões de arquivos aqui (ex. pdf,xls,doc). Uma lista vazia significa que todas as extensões são permitidas.", "profile-avatars": "Avatares de Perfil", "allow-profile-image-uploads": "Permitir usuários de enviar imagens de perfil", "convert-profile-image-png": "Converter imagens de perfil enviadas para PNG", diff --git a/public/language/pt-BR/notifications.json b/public/language/pt-BR/notifications.json index f189833c1d..80e9e18e03 100644 --- a/public/language/pt-BR/notifications.json +++ b/public/language/pt-BR/notifications.json @@ -19,9 +19,9 @@ "user_flagged_post_in": "%1 sinalizou um post em %2", "user_flagged_post_in_dual": "%1 e %2 sinalizaram um post em %3", "user_flagged_post_in_multiple": "%1 e %2 outros sinalizaram um post em %3", - "user_flagged_user": "%1 flagged a user profile (%2)", - "user_flagged_user_dual": "%1 and %2 flagged a user profile (%3)", - "user_flagged_user_multiple": "%1 and %2 others flagged a user profile (%3)", + "user_flagged_user": "%1 sinalizou um perfil de usuário (%2)", + "user_flagged_user_dual": "%1 e %2 sinalizaram um perfil de usuário (%3)", + "user_flagged_user_multiple": "%1 e %2 outros sinalizaram um perfil de usuário (%3)", "user_posted_to": "%1 postou uma resposta para: %2", "user_posted_to_dual": "%1 e %2 postaram respostas para: %3", "user_posted_to_multiple": "%1 e %2 outros postaram respostas para: %3", diff --git a/public/language/pt-BR/pages.json b/public/language/pt-BR/pages.json index 7a27b39a3c..42444ed4bd 100644 --- a/public/language/pt-BR/pages.json +++ b/public/language/pt-BR/pages.json @@ -6,7 +6,7 @@ "popular-month": "Tópicos populares deste mês", "popular-alltime": "Tópicos populares de todos os tempos", "recent": "Tópicos Recentes", - "flagged-content": "Flagged Content", + "flagged-content": "Conteúdo Sinalizado", "ip-blacklist": "Lista negra de IPs", "users/online": "Usuários Online", "users/latest": "Últimos Usuários", @@ -27,8 +27,8 @@ "group": "%1 grupo", "chats": "Chats", "chat": "Conversando com %1", - "flags": "Flags", - "flag-details": "Flag %1 Details", + "flags": "Sinalizações", + "flag-details": "Detalhes da Sinalização %1", "account/edit": "Editando \"%1\"", "account/edit/password": "Editando senha de \"%1\"", "account/edit/username": "Editando nome de usuário de \"%1\"", diff --git a/public/language/pt-BR/search.json b/public/language/pt-BR/search.json index 8cab1cc17d..43d847db48 100644 --- a/public/language/pt-BR/search.json +++ b/public/language/pt-BR/search.json @@ -12,7 +12,7 @@ "reply-count": "Contagem de Respostas", "at-least": "No mínimo", "at-most": "No máximo", - "relevance": "Relevance", + "relevance": "Relevância", "post-time": "Data da postagem", "newer-than": "Mais novo que", "older-than": "Mais antigo que", diff --git a/public/language/pt-BR/topic.json b/public/language/pt-BR/topic.json index 94c012b3e8..483c769ade 100644 --- a/public/language/pt-BR/topic.json +++ b/public/language/pt-BR/topic.json @@ -13,8 +13,8 @@ "notify_me": "Seja notificado de novas respostas nesse tópico", "quote": "Citar", "reply": "Responder", - "replies_to_this_post": "%1 Replies", - "last_reply_time": "Last reply", + "replies_to_this_post": "%1 Respostas", + "last_reply_time": "Última resposta", "reply-as-topic": "Responder como tópico", "guest-login-reply": "Entre para responder", "edit": "Editar", diff --git a/public/language/pt-BR/user.json b/public/language/pt-BR/user.json index d3e5415207..b9e5f94712 100644 --- a/public/language/pt-BR/user.json +++ b/public/language/pt-BR/user.json @@ -33,7 +33,7 @@ "chat": "Chat", "chat_with": "Continuar a conversa com %1", "new_chat_with": "Iniciar uma nova conversa com %1", - "flag-profile": "Flag Profile", + "flag-profile": "Perfil da Sinalização", "follow": "Seguir", "unfollow": "Deixar de Seguir", "more": "Mais", @@ -65,8 +65,8 @@ "remove_uploaded_picture": "Remover Foto Enviada", "upload_cover_picture": "Fazer upload de imagem de capa ", "remove_cover_picture_confirm": "Tem certeza que deseja remover a imagem de capa?", - "crop_picture": "Crop picture", - "upload_cropped_picture": "Crop and upload", + "crop_picture": "Cortar imagem", + "upload_cropped_picture": "Cortar e enviar", "settings": "Configurações", "show_email": "Mostrar Meu Email", "show_fullname": "Mostrar Meu Nome Completo", From 642306e69c9d50e87926ffebeb884716b90aae8a Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Thu, 23 Mar 2017 16:00:22 -0600 Subject: [PATCH 4/6] Fix #5543 --- src/user/create.js | 34 +++++++++++++++++----------------- test/user.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/user/create.js b/src/user/create.js index 2620cb67d3..ab413a545d 100644 --- a/src/user/create.js +++ b/src/user/create.js @@ -46,7 +46,7 @@ module.exports = function (User) { async.parallel({ renamedUsername: function (next) { - renameUsername(userData, next); + User.renameUsername(userData, next); }, userData: function (next) { plugins.fireHook('filter:user.create', { user: userData, data: data }, next); @@ -200,28 +200,28 @@ module.exports = function (User) { callback(); }; - function renameUsername(userData, callback) { + User.renameUsername = function (userData, callback) { meta.userOrGroupExists(userData.userslug, function (err, exists) { if (err || !exists) { return callback(err); } - var newUsername = ''; - async.forever(function (next) { - newUsername = userData.username + (Math.floor(Math.random() * 255) + 1); - User.existsBySlug(newUsername, function (err, exists) { - if (err) { - return callback(err); - } - if (!exists) { - next(newUsername); - } else { - next(); + var num = 0; + + function go() { + var username = userData.username + ' ' + num.toString(32); + var userslug = utils.slugify(username); + meta.userOrGroupExists(userslug, function (err, exists) { + if (err || !exists) { + return callback(err, username); } + + num += 1; + go(); }); - }, function (username) { - callback(null, username); - }); + } + + go(); }); - } + }; }; diff --git a/test/user.js b/test/user.js index 776dbf28de..c83e8cd411 100644 --- a/test/user.js +++ b/test/user.js @@ -70,6 +70,38 @@ describe('User', function () { }); }); + describe('.renameUsername()', function () { + it('should deal with collisions', function (done) { + var users = []; + for (var i = 0; i < 10; i += 1) { + users.push({ + username: 'Jane Doe', + password: 'abcdefghi', + email: 'jane.doe' + i + '@example.com', + }); + } + + async.series([ + function (next) { + async.eachSeries(users, function (user, next) { + User.create(user, next); + }, next); + }, + function (next) { + User.renameUsername({ + username: 'Jane Doe', + userslug: 'jane-doe', + }, function (err, username) { + assert.ifError(err); + + assert.strictEqual(username, 'Jane Doe 9'); + done(); + }); + }, + ], done); + }); + }); + describe('.isModerator()', function () { it('should return false', function (done) { User.isModerator(testUid, testCid, function (err, isModerator) { From a7677063de5f5d1dbc0b087934bc024694e8388b Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Fri, 24 Mar 2017 10:33:38 -0600 Subject: [PATCH 5/6] Rename to `uniqueUsername` --- src/user/create.js | 4 ++-- test/user.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/user/create.js b/src/user/create.js index ab413a545d..c629f76020 100644 --- a/src/user/create.js +++ b/src/user/create.js @@ -46,7 +46,7 @@ module.exports = function (User) { async.parallel({ renamedUsername: function (next) { - User.renameUsername(userData, next); + User.uniqueUsername(userData, next); }, userData: function (next) { plugins.fireHook('filter:user.create', { user: userData, data: data }, next); @@ -200,7 +200,7 @@ module.exports = function (User) { callback(); }; - User.renameUsername = function (userData, callback) { + User.uniqueUsername = function (userData, callback) { meta.userOrGroupExists(userData.userslug, function (err, exists) { if (err || !exists) { return callback(err); diff --git a/test/user.js b/test/user.js index c83e8cd411..08d3ba42d4 100644 --- a/test/user.js +++ b/test/user.js @@ -70,7 +70,7 @@ describe('User', function () { }); }); - describe('.renameUsername()', function () { + describe('.uniqueUsername()', function () { it('should deal with collisions', function (done) { var users = []; for (var i = 0; i < 10; i += 1) { @@ -88,7 +88,7 @@ describe('User', function () { }, next); }, function (next) { - User.renameUsername({ + User.uniqueUsername({ username: 'Jane Doe', userslug: 'jane-doe', }, function (err, username) { From 31b6d47f88b04968e949dab8b9226b0a01cc11b7 Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 24 Mar 2017 14:36:49 -0400 Subject: [PATCH 6/6] fixes #5545 --- src/controllers/api.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controllers/api.js b/src/controllers/api.js index f7158481e7..92a063e88e 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -73,9 +73,9 @@ apiController.getConfig = function (req, res, next) { config.cookies = { enabled: parseInt(meta.config.cookieConsentEnabled, 10) === 1, - message: translator.escape(meta.config.cookieConsentMessage || '[[global:cookies.message]]').replace(/\\/g, '\\\\'), - dismiss: translator.escape(meta.config.cookieConsentDismiss || '[[global:cookies.accept]]').replace(/\\/g, '\\\\'), - link: translator.escape(meta.config.cookieConsentLink || '[[global:cookies.learn_more]]').replace(/\\/g, '\\\\'), + message: translator.escape(validator.escape(meta.config.cookieConsentMessage) || '[[global:cookies.message]]').replace(/\\/g, '\\\\'), + dismiss: translator.escape(validator.escape(meta.config.cookieConsentDismiss) || '[[global:cookies.accept]]').replace(/\\/g, '\\\\'), + link: translator.escape(validator.escape(meta.config.cookieConsentLink) || '[[global:cookies.learn_more]]').replace(/\\/g, '\\\\'), }; async.waterfall([