diff --git a/app.js b/app.js index fb757a497d..acb1a3baca 100644 --- a/app.js +++ b/app.js @@ -46,11 +46,6 @@ winston.add(winston.transports.Console, { level: global.env === 'production' ? 'info' : 'verbose' }); -// TODO: remove once https://github.com/flatiron/winston/issues/280 is fixed -winston.err = function (err) { - winston.error(err.stack); -}; - if(os.platform() === 'linux') { require('child_process').exec('/usr/bin/which convert', function(err, stdout, stderr) { if(err || !stdout) { diff --git a/install/data/defaults.json b/install/data/defaults.json index 5507ad0822..778dee3838 100644 --- a/install/data/defaults.json +++ b/install/data/defaults.json @@ -27,6 +27,10 @@ "field": "minimumPostLength", "value": 8 }, + { + "field": "maximumPostLength", + "value": 32767 + }, { "field": "allowGuestSearching", "value": 0 diff --git a/package.json b/package.json index c46f966b43..22c2570b1a 100644 --- a/package.json +++ b/package.json @@ -59,11 +59,11 @@ "socket.io-redis": "^0.1.3", "socketio-wildcard": "~0.1.1", "string": "^3.0.0", - "templates.js": "0.1.10", + "templates.js": "^0.1.15", "uglify-js": "git+https://github.com/julianlam/UglifyJS2.git", "underscore": "~1.7.0", - "validator": "~3.26.0", - "winston": "^0.8.1", + "validator": "~3.28.0", + "winston": "^0.9.0", "xregexp": "~2.0.0" }, "devDependencies": { diff --git a/public/language/en_GB/error.json b/public/language/en_GB/error.json index 47b0bf8938..0258b28154 100644 --- a/public/language/en_GB/error.json +++ b/public/language/en_GB/error.json @@ -46,6 +46,7 @@ "still-uploading": "Please wait for uploads to complete.", "content-too-short": "Please enter a longer post. Posts should contain at least %1 characters.", + "content-too-long": "Please enter a shorter post. Posts can't be longer than %1 characters.", "title-too-short": "Please enter a longer title. Titles should contain at least %1 characters.", "title-too-long": "Please enter a shorter title. Titles can't be longer than %1 characters.", "invalid-title": "Invalid title!", diff --git a/public/src/client/topic/fork.js b/public/src/client/topic/fork.js index 21f8d06e59..b9695cb81e 100644 --- a/public/src/client/topic/fork.js +++ b/public/src/client/topic/fork.js @@ -35,7 +35,7 @@ define('forum/topic/fork', function() { forkModal.find('.close,#fork_thread_cancel').on('click', closeForkModal); forkModal.find('#fork-title').on('change', checkForkButtonEnable); - $('#post-container').on('click', 'li[data-pid]', function() { + $('#post-container').on('click', '[data-pid]', function() { togglePostSelection($(this)); }); @@ -58,7 +58,7 @@ define('forum/topic/fork', function() { pids: pids }, function(err, newTopic) { function fadeOutAndRemove(pid) { - $('#post-container li[data-pid="' + pid + '"]').fadeOut(500, function() { + $('#post-container [data-pid="' + pid + '"]').fadeOut(500, function() { $(this).remove(); }); } @@ -125,10 +125,10 @@ define('forum/topic/fork', function() { function closeForkModal() { for(var i=0; i parseInt(config.maximumPostLength, 10)) { + return composerAlert('[[error:content-too-long, ' + config.maximumPostLength + ']]'); } var composerData = {}, action; diff --git a/public/src/widgets.js b/public/src/widgets.js index 9e34ba9513..2200f58d5e 100644 --- a/public/src/widgets.js +++ b/public/src/widgets.js @@ -51,12 +51,12 @@ if (!area.length && window.location.pathname.indexOf('/admin') === -1 && renderedWidgets.length) { if (location === 'footer' && !$('#content [widget-area="footer"]').length) { - $('#content').append($('
')); + $('#content').append($('
')); } else if (location === 'sidebar' && !$('#content [widget-area="sidebar"]').length) { - $('#content > *').wrapAll($('
')); - $('#content').append($('
')); + $('#content > *').wrapAll($('
')); + $('#content').append($('
')); } else if (location === 'header' && !$('#content [widget-area="header"]').length) { - $('#content').prepend($('
')); + $('#content').prepend($('
')); } area = $('#content [widget-area="' + location + '"]'); diff --git a/src/categories/recentreplies.js b/src/categories/recentreplies.js index bb1ae32775..596bd6882e 100644 --- a/src/categories/recentreplies.js +++ b/src/categories/recentreplies.js @@ -103,7 +103,10 @@ module.exports = function(Categories) { pids = pids.concat(topicPids).filter(function(pid, index, array) { return !!pid && array.indexOf(pid) === index; - }); + }).sort(function(a, b) { + return b - a; + }).slice(0, count); + callback(null, pids); }); }); diff --git a/src/controllers/accounts.js b/src/controllers/accounts.js index c55977a351..84b0f96ad5 100644 --- a/src/controllers/accounts.js +++ b/src/controllers/accounts.js @@ -466,7 +466,7 @@ accountsController.uploadPicture = function (req, res, next) { fs.unlink(absolutePath, function (err) { if (err) { - winston.err(err); + winston.error(err); } file.saveFileToLocal(filename, 'profile', userPhoto.path, done); diff --git a/src/controllers/admin.js b/src/controllers/admin.js index 6779185f0a..f03b7fdb88 100644 --- a/src/controllers/admin.js +++ b/src/controllers/admin.js @@ -113,11 +113,17 @@ function getStatsForSet(set, field, callback) { db.sortedSetCount(set, now - terms.month, now, next); }, alltime: function(next) { - db.getObjectField('global', field, next); + getGlobalField(field, next); } }, callback); } +function getGlobalField(field, callback) { + db.getObjectField('global', field, function(err, count) { + callback(err, parseInt(count, 10) || 0); + }); +} + adminController.categories.active = function(req, res, next) { filterAndRenderCategories(req, res, next, true); }; diff --git a/src/controllers/api.js b/src/controllers/api.js index be4d8b2347..ae112b9bd6 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -23,6 +23,7 @@ apiController.getConfig = function(req, res, next) { config.minimumTitleLength = meta.config.minimumTitleLength; config.maximumTitleLength = meta.config.maximumTitleLength; config.minimumPostLength = meta.config.minimumPostLength; + config.maximumPostLength = meta.config.maximumPostLength; config.hasImageUploadPlugin = plugins.hasListeners('filter:uploadImage'); config.maximumProfileImageSize = meta.config.maximumProfileImageSize; config.minimumUsernameLength = meta.config.minimumUsernameLength; diff --git a/src/groups.js b/src/groups.js index 462a0854a8..38c8704813 100644 --- a/src/groups.js +++ b/src/groups.js @@ -690,8 +690,14 @@ var async = require('async'), Groups.acceptMembership = function(groupName, uid, callback) { // Note: For simplicity, this method intentially doesn't check the caller uid for ownership! - db.setRemove('group:' + groupName + ':pending', uid, callback); - Groups.join.apply(Groups, arguments); + async.waterfall([ + function(next) { + db.setRemove('group:' + groupName + ':pending', uid, next); + }, + function(next) { + Groups.join(groupName, uid, next); + } + ], callback); }; Groups.rejectMembership = function(groupName, uid, callback) { diff --git a/src/socket.io/groups.js b/src/socket.io/groups.js index 1b97dad0bb..b2b1b244ed 100644 --- a/src/socket.io/groups.js +++ b/src/socket.io/groups.js @@ -13,6 +13,10 @@ SocketGroups.join = function(socket, data, callback) { return callback(new Error('[[error:invalid-data]]')); } + if (!parseInt(socket.uid, 10)) { + return callback(new Error('[[error:invalid-uid]]')); + } + if (meta.config.allowPrivateGroups !== '0') { async.parallel({ isAdmin: async.apply(user.isAdministrator, socket.uid), @@ -34,6 +38,10 @@ SocketGroups.leave = function(socket, data, callback) { return callback(new Error('[[error:invalid-data]]')); } + if (!parseInt(socket.uid, 10)) { + return callback(new Error('[[error:invalid-uid]]')); + } + groups.leave(data.groupName, socket.uid, callback); }; diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index d9f673067c..5ac3cfb759 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -261,6 +261,8 @@ SocketPosts.edit = function(socket, data, callback) { return callback(new Error('[[error:title-too-long, ' + meta.config.maximumTitleLength + ']]')); } else if (!data.content || data.content.length < parseInt(meta.config.minimumPostLength, 10)) { return callback(new Error('[[error:content-too-short, ' + meta.config.minimumPostLength + ']]')); + } else if (data.content.length > parseInt(meta.config.maximumPostLength, 10)) { + return callback(new Error('[[error:content-too-long, ' + meta.config.maximumPostLength + ']]')); } // uid, pid, title, content, options @@ -394,9 +396,6 @@ SocketPosts.flag = function(socket, pid, callback) { post; async.waterfall([ - function(next) { - posts.flag(pid, next); - }, function(next) { user.getUserFields(socket.uid, ['username', 'reputation'], next); }, @@ -405,7 +404,6 @@ SocketPosts.flag = function(socket, pid, callback) { return next(new Error('[[error:not-enough-reputation-to-flag]]')); } userName = userData.username; - posts.getPostFields(pid, ['tid', 'uid', 'content', 'deleted'], next); }, function(postData, next) { @@ -413,7 +411,10 @@ SocketPosts.flag = function(socket, pid, callback) { return next(new Error('[[error:post-deleted]]')); } post = postData; - topics.getTopicFields(postData.tid, ['title', 'cid'], next); + posts.flag(pid, next); + }, + function(next) { + topics.getTopicFields(post.tid, ['title', 'cid'], next); }, function(topic, next) { post.topic = topic; diff --git a/src/topics/create.js b/src/topics/create.js index b3038911c1..2eb882da80 100644 --- a/src/topics/create.js +++ b/src/topics/create.js @@ -289,6 +289,8 @@ module.exports = function(Topics) { function checkContentLength(content, callback) { if (!content || content.length < parseInt(meta.config.miminumPostLength, 10)) { return callback(new Error('[[error:content-too-short, ' + meta.config.minimumPostLength + ']]')); + } else if (content.length > parseInt(meta.config.maximumPostLength, 10)) { + return callback(new Error('[[error:content-too-long, ' + meta.config.maximumPostLength + ']]')); } callback(); } diff --git a/src/topics/posts.js b/src/topics/posts.js index 9e3275887f..d4809f2a79 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -177,7 +177,7 @@ module.exports = function(Topics) { return next(err); } latestPid = pids[0]; - isDeleted = deleted; + isDeleted = parseInt(deleted, 10) === 1; ++index; next(); }); diff --git a/src/views/admin/settings/post.tpl b/src/views/admin/settings/post.tpl index 15f65ef531..3cb55eac0e 100644 --- a/src/views/admin/settings/post.tpl +++ b/src/views/admin/settings/post.tpl @@ -49,6 +49,10 @@ +
+ + +