diff --git a/app.js b/app.js index d3b4af0697..686b355602 100644 --- a/app.js +++ b/app.js @@ -37,7 +37,7 @@ var winston = require('winston'); var path = require('path'); var pkg = require('./package.json'); var file = require('./src/file'); -var debug = require('./src/meta/debugParams')().execArgv.length; +var debug = require('./src/meta/debugFork').debugging; global.env = process.env.NODE_ENV || 'production'; diff --git a/package.json b/package.json index 43045ca080..89456f495d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "nodebb", "license": "GPL-3.0", "description": "NodeBB Forum", - "version": "1.6.0", + "version": "1.6.1", "homepage": "http://www.nodebb.org", "repository": { "type": "git", @@ -65,11 +65,11 @@ "nodebb-plugin-soundpack-default": "1.0.0", "nodebb-plugin-spam-be-gone": "0.5.1", "nodebb-rewards-essentials": "0.0.9", - "nodebb-theme-lavender": "4.1.0", - "nodebb-theme-persona": "6.1.1", + "nodebb-theme-lavender": "4.1.1", + "nodebb-theme-persona": "6.1.3", "nodebb-theme-slick": "1.1.1", - "nodebb-theme-vanilla": "7.1.0", - "nodebb-widget-essentials": "3.0.6", + "nodebb-theme-vanilla": "7.1.2", + "nodebb-widget-essentials": "3.0.7", "nodemailer": "4.1.1", "passport": "^0.4.0", "passport-local": "1.0.0", diff --git a/public/language/cs/admin/settings/email.json b/public/language/cs/admin/settings/email.json index 5a82b3aad5..27d14b96bc 100644 --- a/public/language/cs/admin/settings/email.json +++ b/public/language/cs/admin/settings/email.json @@ -15,10 +15,10 @@ "smtp-transport.gmail-warning2": "Další informace o tomto řešení, konzultujte s NodeMailer.Alternativou je použití e-mailového rozšíření třetích stran jako je SendGrid, Mailgun atd.Dostupné rozšíření zde.", "smtp-transport.host": "Hostitel SMTP", "smtp-transport.port": "Port SMTP", - "smtp-transport.security": "Connection security", - "smtp-transport.security-encrypted": "Encrypted", + "smtp-transport.security": "Zabezpečení připojení", + "smtp-transport.security-encrypted": "Šifrované", "smtp-transport.security-starttls": "StartTLS", - "smtp-transport.security-none": "None", + "smtp-transport.security-none": "Nic", "smtp-transport.username": "Uživatelské jméno", "smtp-transport.username-help": "Pro službu Gmail, zadejte plnou e-mailovou adresu, zvláště, používáte-li spravovanou doménu Google Apps.", "smtp-transport.password": "Heslo", diff --git a/public/language/en-GB/admin/settings/pagination.json b/public/language/en-GB/admin/settings/pagination.json index 27d71b4de5..d565e2d446 100644 --- a/public/language/en-GB/admin/settings/pagination.json +++ b/public/language/en-GB/admin/settings/pagination.json @@ -3,7 +3,9 @@ "enable": "Paginate topics and posts instead of using infinite scroll.", "topics": "Topic Pagination", "posts-per-page": "Posts per Page", + "max-posts-per-page": "Maximum posts per page", "categories": "Category Pagination", "topics-per-page": "Topics per Page", + "max-topics-per-page": "Maximum topics per page", "initial-num-load": "Initial Number of Topics to Load on Unread, Recent, and Popular" } \ No newline at end of file diff --git a/public/language/en-GB/user.json b/public/language/en-GB/user.json index 2f5e588881..ba61113160 100644 --- a/public/language/en-GB/user.json +++ b/public/language/en-GB/user.json @@ -102,6 +102,7 @@ "paginate_description" : "Paginate topics and posts instead of using infinite scroll", "topics_per_page": "Topics per Page", "posts_per_page": "Posts per Page", + "max_items_per_page": "Maximum %1", "notification_sounds" : "Play a sound when you receive a notification", "notifications_and_sounds": "Notifications & Sounds", diff --git a/public/language/fr/admin/settings/email.json b/public/language/fr/admin/settings/email.json index 06846b88cb..b965d5894b 100644 --- a/public/language/fr/admin/settings/email.json +++ b/public/language/fr/admin/settings/email.json @@ -5,20 +5,20 @@ "from": "Nom de l’expéditeur", "from-help": "Le nom de l’expéditeur à afficher dans l'e-mail", - "smtp-transport": "SMTP Transport", + "smtp-transport": "Protocole SMTP", "smtp-transport.enabled": "Utiliser un server extérieur pour envoyer les emails", "smtp-transport-help": "Vous pouvez sélectionner depuis une liste de services ou entrer un service personnalisé.", "smtp-transport.service": "Sélectionner un service", "smtp-transport.service-custom": "Service personnalisé", - "smtp-transport.service-help": "S", - "smtp-transport.gmail-warning1": "There have been reports of the Gmail service not working on accounts with heightened security. In those scenarios, you will have to configure your GMail account to allow less secure apps.", - "smtp-transport.gmail-warning2": "For more information about this workaround, please consult this NodeMailer article on the issue. An alternative would be to utilise a third-party emailer plugin such as SendGrid, Mailgun, etc. Browse available plugins here.", + "smtp-transport.service-help": "Sélectionner un service ci-dessus afin de renseigner les champs. Sinon, sélectionner \"Service Personnalisé\" et ajouter les informations ci-dessous.", + "smtp-transport.gmail-warning1": "Vous pouvez rencontrer des difficultés avec le service Gmail pour les comptes ayant une sécurité élevée. Dans ce cas, vous devez configurer votre compte Gmail pour qu'il autorise les applications moins sécurisées.", + "smtp-transport.gmail-warning2": "Pour plus d'informations à propos de cette solution, consulter l'article sur le NodeMailer sur ce sujet. Une alternative est d'utiliser un service tiers d'envoi d'email tels que SendGrid, Mailgun, etc. Consulter les plugins disponibles ici.", "smtp-transport.host": "Host SMTP", "smtp-transport.port": "Port SMTP", - "smtp-transport.security": "Connection security", - "smtp-transport.security-encrypted": "Encrypted", + "smtp-transport.security": "Accès sécurisé", + "smtp-transport.security-encrypted": "Cryptage", "smtp-transport.security-starttls": "StartTLS", - "smtp-transport.security-none": "None", + "smtp-transport.security-none": "Aucun", "smtp-transport.username": "Nom d'utilisateur", "smtp-transport.username-help": "Pour Gmail, entrer l’adresse e-mail complète ici, surtout si vous utilisez un domaine géré par Google Apps.", "smtp-transport.password": "Mot de passe", diff --git a/public/language/fr/admin/settings/general.json b/public/language/fr/admin/settings/general.json index ee9c180412..5dd47e1379 100644 --- a/public/language/fr/admin/settings/general.json +++ b/public/language/fr/admin/settings/general.json @@ -2,8 +2,8 @@ "site-settings": "Réglages du site", "title": "Titre du site", "title.url": "URL", - "title.url-placeholder": "The URL of the site title", - "title.url-help": "When the title is clicked, send users to this address. If left blank, user will be sent to the forum index.", + "title.url-placeholder": "URL du titre du site", + "title.url-help": "Adresse à laquelle l'utilisateur est renvoyé lors du clic sur le titre. Si ce champ est vide, l'adresse est celle de l'index du forum.", "title.name": "Nom de votre communauté", "title.show-in-header": "Afficher le titre du site dans l'en-tête", "browser-title": "Titre dans le navigateur", diff --git a/public/language/fr/admin/settings/post.json b/public/language/fr/admin/settings/post.json index 560883ff6d..3371e5b6d4 100644 --- a/public/language/fr/admin/settings/post.json +++ b/public/language/fr/admin/settings/post.json @@ -6,8 +6,8 @@ "sorting.most-votes": "Avec le plus de votes", "sorting.topic-default": "Tri des sujets par défaut", "restrictions": "Restrictions d'envoi", - "restrictions.post-queue": "Enable post queue", - "restrictions.post-queue-help": "Enabling post queue will put the posts of new users in a queue for approval.", + "restrictions.post-queue": "Activer la file d'attente des messages", + "restrictions.post-queue-help": "Activer la file d'attente des messages mettra automatiquement les messages des nouveaux utilisateurs dans la liste pour approbation.", "restrictions.seconds-between": "Nombre de secondes entre chaque message", "restrictions.seconds-between-new": "Nombre de secondes entre chaque message pour les nouveaux utilisateurs", "restrictions.rep-threshold": "Seuil de réputation avant que cette restriction soit levée", diff --git a/public/language/fr/error.json b/public/language/fr/error.json index 80c2ba5573..f0989ca856 100644 --- a/public/language/fr/error.json +++ b/public/language/fr/error.json @@ -4,7 +4,7 @@ "not-logged-in": "Vous ne semblez pas être connecté.", "account-locked": "Votre compte a été temporairement suspendu", "search-requires-login": "Rechercher nécessite d'avoir un compte. Veuillez vous identifier ou vous enregistrer.", - "goback": "Press back to return to the previous page", + "goback": "Appuyez sur retour pour revenir à la page précédente", "invalid-cid": "ID de catégorie invalide", "invalid-tid": "ID de sujet invalide", "invalid-pid": "ID de message invalide", diff --git a/public/language/fr/notifications.json b/public/language/fr/notifications.json index f24c13b434..4d34dd3593 100644 --- a/public/language/fr/notifications.json +++ b/public/language/fr/notifications.json @@ -41,7 +41,7 @@ "new_register": "%1 a envoyé une demande d'incription.", "new_register_multiple": "%1 inscription(s) est en attente de validation.", "flag_assigned_to_you": "Drapeau %1 vous a été assigné", - "post_awaiting_review": "Post awaiting review", + "post_awaiting_review": "Message en attente de validation", "email-confirmed": "Email vérifié", "email-confirmed-message": "Merci pour la validation de votre adresse email. Votre compte est désormais activé.", "email-confirm-error-message": "Il y a un un problème dans la vérification de votre adresse email. Le code est peut être invalide ou a expiré.", diff --git a/public/language/fr/pages.json b/public/language/fr/pages.json index 47b5dac051..820f197157 100644 --- a/public/language/fr/pages.json +++ b/public/language/fr/pages.json @@ -9,7 +9,7 @@ "moderator-tools": "Outils de modération", "flagged-content": "Contenu signalé", "ip-blacklist": "Liste noire d'adresses IP", - "post-queue": "Post Queue", + "post-queue": "File d'attente des messages", "users/online": "Utilisateurs en ligne", "users/latest": "Derniers inscrits", "users/sort-posts": "Utilisateurs avec le plus de messages", diff --git a/public/language/fr/success.json b/public/language/fr/success.json index 6064afcc64..11894dcd3f 100644 --- a/public/language/fr/success.json +++ b/public/language/fr/success.json @@ -1,7 +1,7 @@ { "success": "Terminé", "topic-post": "Le message a bien été envoyé.", - "post-queued": "Your post is queued for approval.", + "post-queued": "Votre message est en attente d'approbation.", "authentication-successful": "Authentification réussie", "settings-saved": "Paramètres enregistrés !" } \ No newline at end of file diff --git a/public/language/he/error.json b/public/language/he/error.json index 0599a1b34b..ecf75c2ed2 100644 --- a/public/language/he/error.json +++ b/public/language/he/error.json @@ -4,7 +4,7 @@ "not-logged-in": "נראה שאינך מחובר למערכת.", "account-locked": "חשבונך נחסם באופן זמני", "search-requires-login": "פעולת החיפוש דורשת חשבון - בבקשה התחבר או הרשם.", - "goback": "Press back to return to the previous page", + "goback": "לחץ back לחזרה לעמוד הקודם", "invalid-cid": "זהוי קטגוריה שגוי", "invalid-tid": "זהוי נושא שגוי", "invalid-pid": "זהוי פוסט שגוי", @@ -59,7 +59,7 @@ "post-delete-duration-expired-hours": "You are only allowed to delete posts for %1 hour(s) after posting", "post-delete-duration-expired-hours-minutes": "You are only allowed to delete posts for %1 hour(s) %2 minute(s) after posting", "post-delete-duration-expired-days": "You are only allowed to delete posts for %1 day(s) after posting", - "post-delete-duration-expired-days-hours": "You are only allowed to delete posts for %1 day(s) %2 hour(s) after posting", + "post-delete-duration-expired-days-hours": "אתה מורשה למחוק פוסט רק %1 ימים ו %2 שעות אחרי פרסומו", "cant-delete-topic-has-reply": "אינך יכול למחוק נושא אחרי שכבר הגיבו בו.", "cant-delete-topic-has-replies": "לא ניתן למחוק את הנושא לאחר שקיבל %1 תגובות", "content-too-short": "אנא הכנס פוסט ארוך יותר. פוסטים חייבים להכיל לפחות %1 תווים.", diff --git a/public/language/he/notifications.json b/public/language/he/notifications.json index e58a931827..1cab5188ab 100644 --- a/public/language/he/notifications.json +++ b/public/language/he/notifications.json @@ -41,7 +41,7 @@ "new_register": "%1 שלח בקשת הרשמה.", "new_register_multiple": "ישנן %1 בקשות הרשמה שמחכות לבדיקה.", "flag_assigned_to_you": "דיווח %1 הוקצה עבורך", - "post_awaiting_review": "Post awaiting review", + "post_awaiting_review": "הפוסט ממתין לאישור", "email-confirmed": "כתובת המייל אושרה", "email-confirmed-message": "תודה שאישרת את כתובת המייל שלך. החשבון שלך פעיל כעת.", "email-confirm-error-message": "אירעה שגיאה בעת אישור המייל שלך. ייתכן כי הקוד היה שגוי או פג תוקף.", diff --git a/public/language/he/pages.json b/public/language/he/pages.json index 46a3aa6a5b..617bd93223 100644 --- a/public/language/he/pages.json +++ b/public/language/he/pages.json @@ -6,10 +6,10 @@ "popular-month": "נושאים חמים החודש", "popular-alltime": "הנושאים החמים בכל הזמנים", "recent": "נושאים אחרונים", - "moderator-tools": "Moderator Tools", + "moderator-tools": "כלי מודרטור", "flagged-content": "תוכן מדווח", "ip-blacklist": "רשימת IP שחורה", - "post-queue": "Post Queue", + "post-queue": "פוסטים ממתינים", "users/online": "משתמשים מחוברים", "users/latest": "משתמשים אחרונים", "users/sort-posts": "משתמשים עם המונה הגבוה ביותר", diff --git a/public/language/he/success.json b/public/language/he/success.json index 2b24b55fac..da04fbee46 100644 --- a/public/language/he/success.json +++ b/public/language/he/success.json @@ -1,7 +1,7 @@ { "success": "הצלחה", "topic-post": "העלת פוסט בהצלחה.", - "post-queued": "Your post is queued for approval.", + "post-queued": "הפוסט שלך ממתין לאישור.", "authentication-successful": "הנתונים אומתו בהצלחה", "settings-saved": "הנתונים נשמרו!" } \ No newline at end of file diff --git a/public/language/he/topic.json b/public/language/he/topic.json index e457ea82e1..b9630978ea 100644 --- a/public/language/he/topic.json +++ b/public/language/he/topic.json @@ -59,7 +59,7 @@ "thread_tools.unlock": "הסר נעילה", "thread_tools.move": "הזז נושא", "thread_tools.move_all": "הזז הכל", - "thread_tools.select_category": "Select Category", + "thread_tools.select_category": "בחר קטגוריה", "thread_tools.fork": "שכפל נושא", "thread_tools.delete": "מחק נושא", "thread_tools.delete-posts": "מחק פוסטים", @@ -75,9 +75,9 @@ "load_categories": "טוען קטגוריות", "confirm_move": "הזז", "confirm_fork": "שכפל", - "bookmark": "Bookmark", - "bookmarks": "Bookmarks", - "bookmarks.has_no_bookmarks": "You haven't bookmarked any posts yet.", + "bookmark": "הוסף למועדפים", + "bookmarks": "מועדפים", + "bookmarks.has_no_bookmarks": "לא צירפת אף פוסט למועדפים עדיין", "loading_more_posts": "טוען פוסטים נוספים", "move_topic": "הזז נושא", "move_topics": "הזז נושאים", diff --git a/public/language/pt-BR/admin/settings/email.json b/public/language/pt-BR/admin/settings/email.json index 4b1b67d94e..9a2a3d7a95 100644 --- a/public/language/pt-BR/admin/settings/email.json +++ b/public/language/pt-BR/admin/settings/email.json @@ -15,10 +15,10 @@ "smtp-transport.gmail-warning2": "Para mais informação sobre este workaround, por gentileza consulte este artigo no NodeMailer sobre o assunto.. Uma alternativa seria utilizar um plugin de email terceirizado como o SendGrid, Maigun etc. . Explore pelos plugins disponíveis aqui.", "smtp-transport.host": "Host SMTP", "smtp-transport.port": "Porta SMTP", - "smtp-transport.security": "Connection security", - "smtp-transport.security-encrypted": "Encrypted", + "smtp-transport.security": "Segurança da conexão", + "smtp-transport.security-encrypted": "Encriptada", "smtp-transport.security-starttls": "StartTLS", - "smtp-transport.security-none": "None", + "smtp-transport.security-none": "Nenhuma", "smtp-transport.username": "Nome de usuário", "smtp-transport.username-help": "Para o serviço do Gmail, entre com o endereço de email completo aqui, especiamente se você estiver usando um domínio administrado pelo Google Apps.", "smtp-transport.password": "Senha", diff --git a/public/language/zh-CN/admin/settings/email.json b/public/language/zh-CN/admin/settings/email.json index e08da21512..c9e4bc5d1f 100644 --- a/public/language/zh-CN/admin/settings/email.json +++ b/public/language/zh-CN/admin/settings/email.json @@ -6,8 +6,8 @@ "from-help": "用于邮件中显示的发送者", "smtp-transport": "SMTP 通信", - "smtp-transport.enabled": "使用一个外部邮箱系统来发送邮件", - "smtp-transport-help": "你可以从列表中选取一个已知的服务或自定义。", + "smtp-transport.enabled": "使用一个外部电子邮箱系统来发送邮件", + "smtp-transport-help": "您可以从列表中选取一个已知的服务或自定义。", "smtp-transport.service": "选择服务", "smtp-transport.service-custom": "自定义", "smtp-transport.service-help": "选取一个上方服务以便使用已知的信息。此外,还可以选取 “自定义”并在下方输入配置细节。", @@ -20,7 +20,7 @@ "smtp-transport.security-starttls": "StartTLS", "smtp-transport.security-none": "None", "smtp-transport.username": "用户名", - "smtp-transport.username-help": "对于Gmail服务,请在这里输入完整的电子邮件地址,尤其是如果你使用的是 Google Apps 托管的域名。", + "smtp-transport.username-help": "对于Gmail服务,请在这里输入完整的电子邮箱地址,尤其是如果您使用的是 Google Apps 托管的域名。", "smtp-transport.password": "密码", "template": "编辑电子邮件模板", diff --git a/public/src/modules/pictureCropper.js b/public/src/modules/pictureCropper.js index 3bd8cf1516..5a02962d1a 100644 --- a/public/src/modules/pictureCropper.js +++ b/public/src/modules/pictureCropper.js @@ -1,7 +1,7 @@ 'use strict'; -define('pictureCropper', ['translator', 'cropper', 'benchpress'], function (translator, cropper, Benchpress) { +define('pictureCropper', ['translator', 'cropper', 'benchpress'], function (translator, Cropper, Benchpress) { var module = {}; module.show = function (data, callback) { @@ -46,7 +46,7 @@ define('pictureCropper', ['translator', 'cropper', 'benchpress'], function (tran var img = document.getElementById('cropped-image'); $(img).css('max-height', cropBoxHeight); - var cropperTool = new cropper.default(img, { + var cropperTool = new Cropper(img, { aspectRatio: data.aspectRatio, autoCropArea: 1, viewMode: 1, @@ -122,7 +122,7 @@ define('pictureCropper', ['translator', 'cropper', 'benchpress'], function (tran $(this).addClass('disabled'); cropperTool.destroy(); - cropperTool = new cropper.default(img, { + cropperTool = new Cropper(img, { viewMode: 1, autoCropArea: 1, ready: function () { diff --git a/src/controllers/accounts/settings.js b/src/controllers/accounts/settings.js index 2285f5e2dc..515cb33a4e 100644 --- a/src/controllers/accounts/settings.js +++ b/src/controllers/accounts/settings.js @@ -12,9 +12,7 @@ var db = require('../../database'); var helpers = require('../helpers'); var accountHelpers = require('./helpers'); - -var settingsController = {}; - +var settingsController = module.exports; settingsController.get = function (req, res, callback) { var userData; @@ -91,67 +89,64 @@ settingsController.get = function (req, res, callback) { next(err, data); }); }, - function (data, next) { + function (data) { userData.customSettings = data.customSettings; userData.disableEmailSubscriptions = parseInt(meta.config.disableEmailSubscriptions, 10) === 1; - next(); + + userData.dailyDigestFreqOptions = [ + { value: 'off', name: '[[user:digest_off]]', selected: userData.settings.dailyDigestFreq === 'off' }, + { value: 'day', name: '[[user:digest_daily]]', selected: userData.settings.dailyDigestFreq === 'day' }, + { value: 'week', name: '[[user:digest_weekly]]', selected: userData.settings.dailyDigestFreq === 'week' }, + { value: 'month', name: '[[user:digest_monthly]]', selected: userData.settings.dailyDigestFreq === 'month' }, + ]; + + userData.bootswatchSkinOptions = [ + { name: 'No skin', value: 'noskin' }, + { name: 'Default', value: 'default' }, + { name: 'Cerulean', value: 'cerulean' }, + { name: 'Cosmo', value: 'cosmo' }, + { name: 'Cyborg', value: 'cyborg' }, + { name: 'Darkly', value: 'darkly' }, + { name: 'Flatly', value: 'flatly' }, + { name: 'Journal', value: 'journal' }, + { name: 'Lumen', value: 'lumen' }, + { name: 'Paper', value: 'paper' }, + { name: 'Readable', value: 'readable' }, + { name: 'Sandstone', value: 'sandstone' }, + { name: 'Simplex', value: 'simplex' }, + { name: 'Slate', value: 'slate' }, + { name: 'Spacelab', value: 'spacelab' }, + { name: 'Superhero', value: 'superhero' }, + { name: 'United', value: 'united' }, + { name: 'Yeti', value: 'yeti' }, + ]; + + userData.bootswatchSkinOptions.forEach(function (skin) { + skin.selected = skin.value === userData.settings.bootswatchSkin; + }); + + userData.languages.forEach(function (language) { + language.selected = language.code === userData.settings.userLang; + }); + + userData.disableCustomUserSkins = parseInt(meta.config.disableCustomUserSkins, 10) === 1; + + userData.allowUserHomePage = parseInt(meta.config.allowUserHomePage, 10) === 1; + + userData.hideFullname = parseInt(meta.config.hideFullname, 10) === 1; + userData.hideEmail = parseInt(meta.config.hideEmail, 10) === 1; + + userData.inTopicSearchAvailable = plugins.hasListeners('filter:topic.search'); + + userData.maxTopicsPerPage = parseInt(meta.config.maxTopicsPerPage, 10) || 20; + userData.maxPostsPerPage = parseInt(meta.config.maxPostsPerPage, 10) || 20; + + userData.title = '[[pages:account/settings]]'; + userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:settings]]' }]); + + res.render('account/settings', userData); }, - ], function (err) { - if (err) { - return callback(err); - } - - userData.dailyDigestFreqOptions = [ - { value: 'off', name: '[[user:digest_off]]', selected: userData.settings.dailyDigestFreq === 'off' }, - { value: 'day', name: '[[user:digest_daily]]', selected: userData.settings.dailyDigestFreq === 'day' }, - { value: 'week', name: '[[user:digest_weekly]]', selected: userData.settings.dailyDigestFreq === 'week' }, - { value: 'month', name: '[[user:digest_monthly]]', selected: userData.settings.dailyDigestFreq === 'month' }, - ]; - - - userData.bootswatchSkinOptions = [ - { name: 'No skin', value: 'noskin' }, - { name: 'Default', value: 'default' }, - { name: 'Cerulean', value: 'cerulean' }, - { name: 'Cosmo', value: 'cosmo' }, - { name: 'Cyborg', value: 'cyborg' }, - { name: 'Darkly', value: 'darkly' }, - { name: 'Flatly', value: 'flatly' }, - { name: 'Journal', value: 'journal' }, - { name: 'Lumen', value: 'lumen' }, - { name: 'Paper', value: 'paper' }, - { name: 'Readable', value: 'readable' }, - { name: 'Sandstone', value: 'sandstone' }, - { name: 'Simplex', value: 'simplex' }, - { name: 'Slate', value: 'slate' }, - { name: 'Spacelab', value: 'spacelab' }, - { name: 'Superhero', value: 'superhero' }, - { name: 'United', value: 'united' }, - { name: 'Yeti', value: 'yeti' }, - ]; - - userData.bootswatchSkinOptions.forEach(function (skin) { - skin.selected = skin.value === userData.settings.bootswatchSkin; - }); - - userData.languages.forEach(function (language) { - language.selected = language.code === userData.settings.userLang; - }); - - userData.disableCustomUserSkins = parseInt(meta.config.disableCustomUserSkins, 10) === 1; - - userData.allowUserHomePage = parseInt(meta.config.allowUserHomePage, 10) === 1; - - userData.hideFullname = parseInt(meta.config.hideFullname, 10) === 1; - userData.hideEmail = parseInt(meta.config.hideEmail, 10) === 1; - - userData.inTopicSearchAvailable = plugins.hasListeners('filter:topic.search'); - - userData.title = '[[pages:account/settings]]'; - userData.breadcrumbs = helpers.buildBreadcrumbs([{ text: userData.username, url: '/user/' + userData.userslug }, { text: '[[user:settings]]' }]); - - res.render('account/settings', userData); - }); + ], callback); }; diff --git a/src/controllers/category.js b/src/controllers/category.js index 8edc68d076..c7414fc096 100644 --- a/src/controllers/category.js +++ b/src/controllers/category.js @@ -187,8 +187,11 @@ function addTags(categoryData, res) { ]; if (categoryData.backgroundImage) { + if (!categoryData.backgroundImage.startsWith('http')) { + categoryData.backgroundImage = nconf.get('url') + categoryData.backgroundImage; + } res.locals.metaTags.push({ - name: 'og:image', + property: 'og:image', content: categoryData.backgroundImage, }); } diff --git a/src/controllers/index.js b/src/controllers/index.js index dbd41d360c..627107b920 100644 --- a/src/controllers/index.js +++ b/src/controllers/index.js @@ -390,8 +390,10 @@ Controllers.manifest = function (req, res) { Controllers.outgoing = function (req, res, next) { var url = req.query.url || ''; + var allowedProtocols = ['http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp', 'webcal']; + var parsed = require('url').parse(url); - if (!url) { + if (!url || !allowedProtocols.includes(parsed.protocol.slice(0, -1))) { return next(); } diff --git a/src/controllers/topics.js b/src/controllers/topics.js index 347ae8e847..d3a4846390 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -227,6 +227,8 @@ function addTags(topicData, req, res) { var ogImageUrl = ''; if (topicData.thumb) { ogImageUrl = topicData.thumb; + } else if (topicData.category.backgroundImage && (!postAtIndex || !postAtIndex.index)) { + ogImageUrl = topicData.category.backgroundImage; } else if (postAtIndex && postAtIndex.user && postAtIndex.user.picture) { ogImageUrl = postAtIndex.user.picture; } else if (meta.config['og:image']) { diff --git a/src/meta/debugFork.js b/src/meta/debugFork.js new file mode 100644 index 0000000000..575eebd610 --- /dev/null +++ b/src/meta/debugFork.js @@ -0,0 +1,41 @@ +'use strict'; + +var fork = require('child_process').fork; + +var debugArg = process.execArgv.find(function (arg) { + return /^--(debug|inspect)/.test(arg); +}); +var debugging = !!debugArg; + +debugArg = debugArg ? debugArg.replace('-brk', '').split('=') : ['--debug', 5859]; +var lastAddress = parseInt(debugArg[1], 10); + +/** + * child-process.fork, but safe for use in debuggers + * @param {string} modulePath + * @param {string[]} [args] + * @param {any} [options] + */ +function debugFork(modulePath, args, options) { + var execArgv = []; + if (global.v8debug || debugging) { + lastAddress += 1; + + execArgv = [debugArg[0] + '=' + lastAddress, '--nolazy']; + } + + if (!Array.isArray(args)) { + options = args; + args = []; + } + + options = options || {}; + options = Object.assign({}, options, { + execArgv: execArgv, + }); + + return fork(modulePath, args, options); +} +debugFork.debugging = debugging; + +module.exports = debugFork; diff --git a/src/meta/debugParams.js b/src/meta/debugParams.js deleted file mode 100644 index 6b84500bff..0000000000 --- a/src/meta/debugParams.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -module.exports = function (execArgv) { - execArgv = execArgv || process.execArgv; - var debugArg = execArgv.find(function (arg) { - return /^--(debug|inspect)/.test(arg); - }); - if (global.v8debug || debugArg) { - debugArg = debugArg ? debugArg.split('=') : ['--debug', 5859]; - var num = parseInt(debugArg[1], 10) + 1; - - return { execArgv: [debugArg[0] + '=' + num, '--nolazy'] }; - } - - return { execArgv: [] }; -}; diff --git a/src/meta/minifier.js b/src/meta/minifier.js index 3b26f99ec5..c51f41578b 100644 --- a/src/meta/minifier.js +++ b/src/meta/minifier.js @@ -1,7 +1,6 @@ 'use strict'; var fs = require('fs'); -var childProcess = require('child_process'); var os = require('os'); var uglifyjs = require('uglify-js'); var async = require('async'); @@ -11,7 +10,7 @@ var postcss = require('postcss'); var autoprefixer = require('autoprefixer'); var clean = require('postcss-clean'); -var debugParams = require('./debugParams'); +var fork = require('./debugFork'); var Minifier = module.exports; @@ -47,13 +46,12 @@ function getChild() { return free.shift(); } - var forkProcessParams = debugParams(); - var proc = childProcess.fork(__filename, [], Object.assign({}, forkProcessParams, { + var proc = fork(__filename, [], { cwd: __dirname, env: { minifier_child: true, }, - })); + }); pool.push(proc); return proc; diff --git a/src/middleware/header.js b/src/middleware/header.js index ec454936e0..4b667ad954 100644 --- a/src/middleware/header.js +++ b/src/middleware/header.js @@ -79,6 +79,7 @@ module.exports = function (middleware) { uid: 0, username: '[[global:guest]]', userslug: '', + fullname: '[[global:guest]]', email: '', picture: user.getDefaultAvatar(), status: 'offline', diff --git a/src/password.js b/src/password.js index 137382c993..6cc1e1776a 100644 --- a/src/password.js +++ b/src/password.js @@ -1,9 +1,8 @@ 'use strict'; -var fork = require('child_process').fork; var path = require('path'); -var debugParams = require('./meta/debugParams'); +var fork = require('./meta/debugFork'); exports.hash = function (rounds, password, callback) { forkChild({ type: 'hash', rounds: rounds, password: password }, callback); @@ -17,7 +16,7 @@ exports.compare = function (password, hash, callback) { }; function forkChild(message, callback) { - var child = fork(path.join(__dirname, 'bcrypt'), [], debugParams()); + var child = fork(path.join(__dirname, 'bcrypt')); child.on('message', function (msg) { if (msg.err) { diff --git a/src/posts/user.js b/src/posts/user.js index dd050ddd3e..2ada0b2dd3 100644 --- a/src/posts/user.js +++ b/src/posts/user.js @@ -12,12 +12,21 @@ module.exports = function (Posts) { Posts.getUserInfoForPosts = function (uids, uid, callback) { var groupsMap = {}; var userData; + var userSettings; async.waterfall([ function (next) { - user.getUsersFields(uids, ['uid', 'username', 'fullname', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status', 'lastonline', 'groupTitle'], next); + async.parallel({ + userData: function (next) { + user.getUsersFields(uids, ['uid', 'username', 'fullname', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status', 'lastonline', 'groupTitle'], next); + }, + userSettings: function (next) { + user.getMultipleUserSettings(uids, next); + }, + }, next); }, - function (_userData, next) { - userData = _userData; + function (results, next) { + userData = results.userData; + userSettings = results.userSettings; var groupTitles = userData.map(function (userData) { return userData && userData.groupTitle; }).filter(function (groupTitle, index, array) { @@ -38,7 +47,7 @@ module.exports = function (Posts) { } }); - userData.forEach(function (userData) { + userData.forEach(function (userData, index) { userData.uid = userData.uid || 0; userData.username = userData.username || '[[global:guest]]'; userData.userslug = userData.userslug || ''; @@ -48,7 +57,7 @@ module.exports = function (Posts) { userData.picture = userData.picture || ''; userData.status = user.getStatus(userData); userData.signature = validator.escape(String(userData.signature || '')); - userData.fullname = validator.escape(String(userData.fullname || '')); + userData.fullname = userSettings[index].showfullname ? validator.escape(String(userData.fullname || '')) : undefined; if (parseInt(meta.config.hideFullname, 10) === 1) { userData.fullname = undefined; } diff --git a/src/topics.js b/src/topics.js index d4f78801aa..5f744316c0 100644 --- a/src/topics.js +++ b/src/topics.js @@ -115,6 +115,9 @@ Topics.getTopicsByTids = function (tids, uid, callback) { users: function (next) { user.getUsersFields(uids, ['uid', 'username', 'fullname', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status'], next); }, + userSettings: function (next) { + user.getMultipleUserSettings(uids, next); + }, categories: function (next) { categories.getCategoriesFields(cids, ['cid', 'name', 'slug', 'icon', 'image', 'bgColor', 'color', 'disabled'], next); }, @@ -136,11 +139,11 @@ Topics.getTopicsByTids = function (tids, uid, callback) { }, next); }, function (results, next) { - if (parseInt(meta.config.hideFullname, 10) === 1) { - results.users.forEach(function (user) { + results.users.forEach(function (user, index) { + if (parseInt(meta.config.hideFullname, 10) === 1 || !results.userSettings[index].showfullname) { user.fullname = undefined; - }); - } + } + }); var users = _.zipObject(uids, results.users); var categories = _.zipObject(cids, results.categories); diff --git a/src/upgrades/1.6.0/generate-email-logo.js b/src/upgrades/1.6.0/generate-email-logo.js index 0e95c3b384..6115e773a1 100644 --- a/src/upgrades/1.6.0/generate-email-logo.js +++ b/src/upgrades/1.6.0/generate-email-logo.js @@ -45,7 +45,7 @@ module.exports = { } meta.configs.setMultiple({ - 'brand:logo': path.join(nconf.get('upload_path'), 'system', path.basename(meta.config['brand:logo'])), + 'brand:logo': path.join('/assets/uploads/system', path.basename(meta.config['brand:logo'])), 'brand:emailLogo': '/assets/uploads/system/site-logo-x50.png', }, next); }, diff --git a/src/user/settings.js b/src/user/settings.js index 42c78a54ba..1a42222acf 100644 --- a/src/user/settings.js +++ b/src/user/settings.js @@ -12,7 +12,7 @@ var pubsub = require('../pubsub'); var LRU = require('lru-cache'); var cache = LRU({ - max: 1000, + max: 2000, length: function () { return 1; }, maxAge: 1000 * 60 * 60, }); @@ -135,12 +135,14 @@ module.exports = function (User) { } User.saveSettings = function (uid, data, callback) { - if (!data.postsPerPage || parseInt(data.postsPerPage, 10) <= 1 || parseInt(data.postsPerPage, 10) > meta.config.postsPerPage) { - return callback(new Error('[[error:invalid-pagination-value, 2, ' + meta.config.postsPerPage + ']]')); + var maxPostsPerPage = meta.config.maxPostsPerPage || 20; + if (!data.postsPerPage || parseInt(data.postsPerPage, 10) <= 1 || parseInt(data.postsPerPage, 10) > maxPostsPerPage) { + return callback(new Error('[[error:invalid-pagination-value, 2, ' + maxPostsPerPage + ']]')); } - if (!data.topicsPerPage || parseInt(data.topicsPerPage, 10) <= 1 || parseInt(data.topicsPerPage, 10) > meta.config.topicsPerPage) { - return callback(new Error('[[error:invalid-pagination-value, 2, ' + meta.config.topicsPerPage + ']]')); + var maxTopicsPerPage = meta.config.maxTopicsPerPage || 20; + if (!data.topicsPerPage || parseInt(data.topicsPerPage, 10) <= 1 || parseInt(data.topicsPerPage, 10) > maxTopicsPerPage) { + return callback(new Error('[[error:invalid-pagination-value, 2, ' + maxTopicsPerPage + ']]')); } data.userLang = data.userLang || meta.config.defaultLang; @@ -153,8 +155,8 @@ module.exports = function (User) { openOutgoingLinksInNewTab: data.openOutgoingLinksInNewTab, dailyDigestFreq: data.dailyDigestFreq || 'off', usePagination: data.usePagination, - topicsPerPage: Math.min(data.topicsPerPage, parseInt(meta.config.topicsPerPage, 10) || 20), - postsPerPage: Math.min(data.postsPerPage, parseInt(meta.config.postsPerPage, 10) || 20), + topicsPerPage: Math.min(data.topicsPerPage, parseInt(maxTopicsPerPage, 10) || 20), + postsPerPage: Math.min(data.postsPerPage, parseInt(maxPostsPerPage, 10) || 20), userLang: data.userLang || meta.config.defaultLang, followTopicsOnCreate: data.followTopicsOnCreate, followTopicsOnReply: data.followTopicsOnReply, diff --git a/src/views/admin/settings/pagination.tpl b/src/views/admin/settings/pagination.tpl index 5caa8d99cd..5f4d77bde3 100644 --- a/src/views/admin/settings/pagination.tpl +++ b/src/views/admin/settings/pagination.tpl @@ -18,7 +18,8 @@