diff --git a/nodebb b/nodebb
index d33baeba04..26ec782725 100755
--- a/nodebb
+++ b/nodebb
@@ -56,7 +56,7 @@ case "$1" in
echo "Launching NodeBB in \"development\" mode."
echo "To run the production build of NodeBB, please use \"forever\"."
echo "More Information: https://github.com/designcreateplay/NodeBB/wiki/How-to-run-NodeBB"
- NODE_ENV=development supervisor -q --extensions 'node|js|tpl' -- loader "$@"
+ NODE_ENV=development supervisor -q --extensions 'node|js|tpl' -- app "$@"
;;
*)
diff --git a/public/src/forum/admin/index.js b/public/src/forum/admin/index.js
index 1870884328..7c9f6db3bd 100644
--- a/public/src/forum/admin/index.js
+++ b/public/src/forum/admin/index.js
@@ -35,6 +35,17 @@ define(function() {
$('.restart').on('click', function() {
socket.emit('admin.restart');
});
+
+ socket.emit('admin.getVisitorCount', function(err, data) {
+ if(err) {
+ return app.alertError(err.message);
+ }
+
+ var uniqueVisitors = $('#unique-visitors');
+ for(var key in data) {
+ uniqueVisitors.find('#' + key).text(data[key]);
+ }
+ });
};
Admin.updateRoomUsage = function(err, data) {
diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js
index 84eafc8621..9a86aaec32 100644
--- a/public/src/forum/topic.js
+++ b/public/src/forum/topic.js
@@ -141,16 +141,16 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
}
loadingEl.remove();
- categoriesEl.on('click', function(e) {
- var el = $(e.target);
+ categoriesEl.on('click', 'li[data-cid]', function(e) {
+ var el = $(this);
if (el.is('li')) {
- confirmCat.html(e.target.innerHTML);
+ confirmCat.html(el.html());
confirmDiv.css({display: 'block'});
targetCid = el.attr('data-cid');
- targetCatLabel = e.html();
+ targetCatLabel = el.html();
commitEl.prop('disabled', false);
}
- }, false);
+ });
commitEl.on('click', function() {
if (!commitEl.prop('disabled') && targetCid) {
@@ -322,11 +322,10 @@ define(['composer', 'forum/pagination'], function(composer, pagination) {
localStorage.removeItem('topic:' + tid + ':bookmark');
}
});
- updateHeader();
- } else {
- updateHeader();
}
+ updateHeader();
+
$('#post-container').on('mouseenter', '.favourite-tooltip', function(e) {
if (!$(this).data('users-loaded')) {
$(this).data('users-loaded', "true");
diff --git a/public/templates/admin/index.tpl b/public/templates/admin/index.tpl
index 2d548c459c..3fac2b0917 100644
--- a/public/templates/admin/index.tpl
+++ b/public/templates/admin/index.tpl
@@ -36,4 +36,29 @@
+
\ No newline at end of file
diff --git a/src/meta.js b/src/meta.js
index f4411904fd..93f53e04d3 100644
--- a/src/meta.js
+++ b/src/meta.js
@@ -3,6 +3,7 @@ var fs = require('fs'),
async = require('async'),
winston = require('winston'),
nconf = require('nconf'),
+ _ = require('underscore'),
utils = require('./../public/src/utils'),
translator = require('./../public/src/translator'),
@@ -250,14 +251,19 @@ var fs = require('fs'),
jsPath = path.normalize(jsPath);
if (jsPath.substring(0, 7) === 'plugins') {
- var paths = jsPath.split(path.sep),
- mappedPath = paths[1];
+ var matches = _.map(plugins.staticDirs, function(realPath, mappedPath) {
+ if (jsPath.match(mappedPath)) {
+ return mappedPath;
+ } else {
+ return null;
+ }
+ }).filter(function(a) { return a; });
- if (plugins.staticDirs[mappedPath]) {
- jsPath = jsPath.replace(path.join('plugins', mappedPath), '');
- return path.join(plugins.staticDirs[mappedPath], jsPath);
+ if (matches.length) {
+ var relPath = jsPath.slice(new String('plugins/' + matches[0]).length);
+ return plugins.staticDirs[matches[0]] + relPath;
} else {
- winston.warn('[meta.scripts.get] Could not resolve mapped path: ' + mappedPath + '. Are you sure it is defined by a plugin?');
+ winston.warn('[meta.scripts.get] Could not resolve mapped path: ' + jsPath + '. Are you sure it is defined by a plugin?');
return null;
}
} else {
diff --git a/src/plugins.js b/src/plugins.js
index 4d01840498..f334d8b0da 100644
--- a/src/plugins.js
+++ b/src/plugins.js
@@ -246,24 +246,31 @@ var fs = require('fs'),
`data.priority`, the relative priority of the method when it is eventually called (default: 10)
*/
- if (data.hook && data.method) {
+ var method;
+
+ if (data.hook && data.method && typeof data.method === 'string' && data.method.length > 0) {
data.id = id;
if (!data.priority) data.priority = 10;
- data.method = data.method.split('.').reduce(function(memo, prop) {
- if (memo[prop]) {
+ method = data.method.split('.').reduce(function(memo, prop) {
+ if (memo !== null && memo[prop]) {
return memo[prop];
} else {
- // Couldn't find method by path, assuming property with periods in it (evil!)
- Plugins.libraries[data.id][data.method];
+ // Couldn't find method by path, aborting
+ return null;
}
}, Plugins.libraries[data.id]);
+ if (method === null) {
+ winston.warn('[plugins/' + id + '] Hook method mismatch: ' + data.hook + ' => ' + data.method);
+ return callback();
+ }
+
+ // Write the actual method reference to the hookObj
+ data.method = method;
+
Plugins.loadedHooks[data.hook] = Plugins.loadedHooks[data.hook] || [];
Plugins.loadedHooks[data.hook].push(data);
- if (global.env === 'development') {
- winston.info('[plugins] Hook registered: ' + data.hook + ' will call ' + id);
- }
callback();
} else return;
};
diff --git a/src/postTools.js b/src/postTools.js
index a097df2d30..b610e19415 100644
--- a/src/postTools.js
+++ b/src/postTools.js
@@ -90,9 +90,7 @@ var winston = require('winston'),
topics.setTopicField(tid, 'thumb', options.topic_thumb);
- db.searchRemove('topic', tid, function() {
- db.searchIndex('topic', title, tid);
- });
+ plugins.fireHook('action:topic.edit', tid);
}
posts.getPostData(pid, function(err, postData) {
diff --git a/src/posts.js b/src/posts.js
index 18d71deb0f..ac428870d0 100644
--- a/src/posts.js
+++ b/src/posts.js
@@ -92,10 +92,10 @@ var db = require('./database'),
return next(err);
}
- postData.content = content;
-
plugins.fireHook('action:post.save', postData);
+ postData.content = content;
+
next(null, postData);
});
}
diff --git a/src/routes/api.js b/src/routes/api.js
index a57f17d2b1..3d61acedf3 100644
--- a/src/routes/api.js
+++ b/src/routes/api.js
@@ -30,6 +30,8 @@ var path = require('path'),
user.updateLastOnlineTime(req.user.uid);
}
+ db.sortedSetAdd('ip:recent', Date.now(), req.ip || 'Unknown');
+
next();
});
@@ -222,15 +224,13 @@ var path = require('path'),
return res.redirect('/404');
}
- var limit = 50;
-
function searchPosts(callback) {
Plugins.fireHook('filter:search.query', {
index: 'post',
- query: req.params.terms
+ query: req.params.term
}, function(err, pids) {
if (err) {
- return callback(err, null);
+ return callback(err);
}
posts.getPostSummaryByPids(pids, false, callback);
@@ -240,10 +240,10 @@ var path = require('path'),
function searchTopics(callback) {
Plugins.fireHook('filter:search.query', {
index: 'topic',
- query: req.params.terms
+ query: req.params.term
}, function(err, tids) {
if (err) {
- return callback(err, null);
+ return callback(err);
}
topics.getTopicsByTids(tids, 0, callback);
diff --git a/src/routes/plugins.js b/src/routes/plugins.js
index 774fee7217..00f37d8d02 100644
--- a/src/routes/plugins.js
+++ b/src/routes/plugins.js
@@ -44,7 +44,7 @@ var nconf = require('nconf'),
if (matches) {
async.map(matches, function(mappedPath, next) {
- var filePath = path.join(plugins.staticDirs[mappedPath], relPath.slice(mappedPath.length));
+ var filePath = path.join(plugins.staticDirs[mappedPath], decodeURIComponent(relPath.slice(mappedPath.length)));
fs.exists(filePath, function(exists) {
if (exists) {
diff --git a/src/socket.io/admin.js b/src/socket.io/admin.js
index 3d5fd87726..316d77a347 100644
--- a/src/socket.io/admin.js
+++ b/src/socket.io/admin.js
@@ -9,6 +9,7 @@ var groups = require('../groups'),
categories = require('../categories'),
CategoryTools = require('../categoryTools'),
logger = require('../logger'),
+ db = require('../database'),
admin = {
user: require('../admin/user'),
categories: require('../admin/categories')
@@ -35,6 +36,30 @@ SocketAdmin.restart = function(socket, data, callback) {
meta.restart();
};
+
+SocketAdmin.getVisitorCount = function(socket, data, callback) {
+ var terms = {
+ day: 86400000,
+ week: 604800000,
+ month: 2592000000
+ };
+ var now = Date.now();
+ async.parallel({
+ day: function(next) {
+ db.sortedSetCount('ip:recent', now - terms.day, now, next);
+ },
+ week: function(next) {
+ db.sortedSetCount('ip:recent', now - terms.week, now, next);
+ },
+ month: function(next) {
+ db.sortedSetCount('ip:recent', now - terms.month, now, next);
+ },
+ alltime: function(next) {
+ db.sortedSetCount('ip:recent', 0, now, next);
+ }
+ }, callback);
+}
+
/* Topics */
SocketAdmin.topics = {};
diff --git a/src/webserver.js b/src/webserver.js
index 220cb6e9b3..44b2186d93 100644
--- a/src/webserver.js
+++ b/src/webserver.js
@@ -392,9 +392,6 @@ process.on('uncaughtException', function(err) {
// Disable framing
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
- // Log IP address
- db.sortedSetAdd('ip:recent', +new Date(), req.ip || 'Unknown');
-
next();
});