From 1ed571189c5a946a4c7bd741c32814ffe2e4a645 Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak <p.jaszkow@gmail.com>
Date: Sat, 8 Apr 2017 20:22:21 -0600
Subject: [PATCH 1/2] Make utils and translator easier to require

Move utils.walk to file.walk, backwards compatible
---
 .eslintrc                              |  2 +-
 public/src/utils.js                    | 78 +++++---------------------
 src/admin/search.js                    |  6 +-
 src/batch.js                           |  2 +-
 src/categories/create.js               |  2 +-
 src/categories/update.js               |  4 +-
 src/controllers/accounts/helpers.js    |  2 +-
 src/controllers/admin/categories.js    |  2 +-
 src/controllers/admin/settings.js      |  4 +-
 src/controllers/api.js                 |  2 +-
 src/controllers/authentication.js      |  2 +-
 src/controllers/category.js            |  2 +-
 src/controllers/topics.js              |  2 +-
 src/database/mongo/sorted.js           |  2 +-
 src/database/redis/sorted.js           |  2 +-
 src/emailer.js                         |  2 +-
 src/events.js                          |  2 +-
 src/file.js                            | 47 +++++++++++++++-
 src/groups.js                          |  2 +-
 src/groups/create.js                   |  2 +-
 src/groups/data.js                     |  2 +-
 src/groups/delete.js                   |  2 +-
 src/groups/membership.js               |  2 +-
 src/groups/update.js                   |  2 +-
 src/install.js                         |  2 +-
 src/messaging.js                       |  2 +-
 src/messaging/data.js                  |  2 +-
 src/meta.js                            |  2 +-
 src/meta/css.js                        |  3 +-
 src/meta/js.js                         |  5 +-
 src/meta/languages.js                  |  5 +-
 src/meta/templates.js                  |  6 +-
 src/middleware/render.js               |  2 +-
 src/navigation/admin.js                |  2 +-
 src/navigation/index.js                |  2 +-
 src/notifications.js                   |  2 +-
 src/plugins.js                         |  3 +-
 src/posts.js                           |  2 +-
 src/posts/create.js                    |  2 +-
 src/posts/edit.js                      |  2 +-
 src/posts/parse.js                     |  2 +-
 src/posts/summary.js                   |  2 +-
 src/posts/topics.js                    |  2 +-
 src/search.js                          |  2 +-
 src/sitemap.js                         |  2 +-
 src/socket.io/groups.js                |  2 +-
 src/socket.io/modules.js               |  2 +-
 src/socket.io/notifications.js         |  2 +-
 src/socket.io/posts.js                 |  2 +-
 src/socket.io/posts/flag.js            |  2 +-
 src/socket.io/topics/infinitescroll.js |  2 +-
 src/socket.io/topics/tags.js           |  2 +-
 src/topics.js                          |  2 +-
 src/topics/create.js                   |  2 +-
 src/topics/data.js                     |  2 +-
 src/topics/tags.js                     |  2 +-
 src/topics/teaser.js                   |  2 +-
 src/topics/unread.js                   |  2 +-
 src/translator.js                      |  3 +
 src/user/approval.js                   |  4 +-
 src/user/create.js                     |  2 +-
 src/user/data.js                       |  2 +-
 src/user/digest.js                     |  2 +-
 src/user/email.js                      |  4 +-
 src/user/invite.js                     |  4 +-
 src/user/profile.js                    |  2 +-
 src/user/reset.js                      |  4 +-
 src/utils.js                           |  3 +
 src/widgets/index.js                   |  2 +-
 69 files changed, 141 insertions(+), 148 deletions(-)
 create mode 100644 src/translator.js
 create mode 100644 src/utils.js

diff --git a/.eslintrc b/.eslintrc
index 52211a126d..bbba3aa94e 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -32,6 +32,7 @@
 		"no-prototype-builtins": "off",
 		"new-cap": "off",
 		"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
+		"import/no-unresolved": "error",
 
 		// ES6
 		"prefer-rest-params": "off",
@@ -43,7 +44,6 @@
 		"vars-on-top": "off",
 
 		// TODO
-		"import/no-unresolved": "off",
 		"import/no-extraneous-dependencies": "off",
 		"import/no-dynamic-require": "off",
 		"import/newline-after-import": "off",
diff --git a/public/src/utils.js b/public/src/utils.js
index 171e3d86db..622b8281a9 100644
--- a/public/src/utils.js
+++ b/public/src/utils.js
@@ -1,13 +1,12 @@
 'use strict';
 
-(function (module) {
-	var utils;
-	var fs;
-	var XRegExp;
-
-	if (typeof window === 'undefined') {
-		fs = require('fs');
-		XRegExp = require('xregexp');
+(function (factory) {
+	if (typeof module === 'object' && module.exports) {
+		var file = require('../../src/file');
+		module.exports = factory(require('xregexp'));
+		module.exports.walk = function (dir, done) {
+			file.walk(dir, done);
+		};
 
 		process.profile = function (operation, start) {
 			console.log('%s took %d milliseconds', operation, process.elapsedTimeSince(start));
@@ -18,11 +17,10 @@
 			return (diff[0] * 1e3) + (diff[1] / 1e6);
 		};
 	} else {
-		XRegExp = window.XRegExp;
+		window.utils = factory(window.XRegExp);
 	}
-
-
-	utils = {
+}(function (XRegExp) {
+	var utils = {
 		generateUUID: function () {
 			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
 				var r = Math.random() * 16 | 0;
@@ -31,49 +29,6 @@
 			});
 		},
 
-		// Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search
-		walk: function (dir, done) {
-			var results = [];
-
-			fs.readdir(dir, function (err, list) {
-				if (err) {
-					return done(err);
-				}
-				var pending = list.length;
-				if (!pending) {
-					return done(null, results);
-				}
-				list.forEach(function (file) {
-					file = dir + '/' + file;
-					fs.stat(file, function (err, stat) {
-						if (err) {
-							return done(err);
-						}
-
-						if (stat && stat.isDirectory()) {
-							utils.walk(file, function (err, res) {
-								if (err) {
-									return done(err);
-								}
-
-								results = results.concat(res);
-								pending -= 1;
-								if (!pending) {
-									done(null, results);
-								}
-							});
-						} else {
-							results.push(file);
-							pending -= 1;
-							if (!pending) {
-								done(null, results);
-							}
-						}
-					});
-				});
-			});
-		},
-
 		invalidUnicodeChars: XRegExp('[^\\p{L}\\s\\d\\-_]', 'g'),
 		invalidLatinChars: /[^\w\s\d\-_]/g,
 		trimRegex: /^\s+|\s+$/g,
@@ -447,11 +402,6 @@
 		},
 	};
 
-	module.exports = utils;
-	if (typeof window !== 'undefined') {
-		window.utils = module.exports;
-	}
-
 		/* eslint "no-extend-native": "off" */
 	if (typeof String.prototype.startsWith !== 'function') {
 		String.prototype.startsWith = function (prefix) {
@@ -479,8 +429,6 @@
 			return this.replace(/\s+$/g, '');
 		};
 	}
-}(typeof module === 'undefined' ? {
-	module: {
-		exports: {},
-	},
-} : module));
+
+	return utils;
+}));
diff --git a/src/admin/search.js b/src/admin/search.js
index 3a6f52cfd0..6ffd9db768 100644
--- a/src/admin/search.js
+++ b/src/admin/search.js
@@ -6,8 +6,8 @@ var async = require('async');
 var sanitizeHTML = require('sanitize-html');
 var nconf = require('nconf');
 
-var utils = require('../../public/src/utils');
-var Translator = require('../../public/src/modules/translator').Translator;
+var file = require('../file');
+var Translator = require('../translator').Translator;
 
 function filterDirectories(directories) {
 	return directories.map(function (dir) {
@@ -24,7 +24,7 @@ function filterDirectories(directories) {
 }
 
 function getAdminNamespaces(callback) {
-	utils.walk(path.resolve(nconf.get('views_dir'), 'admin'), function (err, directories) {
+	file.walk(path.resolve(nconf.get('views_dir'), 'admin'), function (err, directories) {
 		if (err) {
 			return callback(err);
 		}
diff --git a/src/batch.js b/src/batch.js
index cb3fd298a1..475c4aa7ca 100644
--- a/src/batch.js
+++ b/src/batch.js
@@ -4,7 +4,7 @@
 
 var async = require('async');
 var db = require('./database');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
 var DEFAULT_BATCH_SIZE = 100;
 
diff --git a/src/categories/create.js b/src/categories/create.js
index 7be163bd5b..90380c0de0 100644
--- a/src/categories/create.js
+++ b/src/categories/create.js
@@ -6,7 +6,7 @@ var db = require('../database');
 var groups = require('../groups');
 var plugins = require('../plugins');
 var privileges = require('../privileges');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Categories) {
 	Categories.create = function (data, callback) {
diff --git a/src/categories/update.js b/src/categories/update.js
index 04bf0e2235..866e6cd748 100644
--- a/src/categories/update.js
+++ b/src/categories/update.js
@@ -5,8 +5,8 @@ var async = require('async');
 
 var db = require('../database');
 var meta = require('../meta');
-var utils = require('../../public/src/utils');
-var translator = require('../../public/src/modules/translator');
+var utils = require('../utils');
+var translator = require('../translator');
 var plugins = require('../plugins');
 
 module.exports = function (Categories) {
diff --git a/src/controllers/accounts/helpers.js b/src/controllers/accounts/helpers.js
index 1ee9a08678..2a40e4044d 100644
--- a/src/controllers/accounts/helpers.js
+++ b/src/controllers/accounts/helpers.js
@@ -9,7 +9,7 @@ var user = require('../../user');
 var groups = require('../../groups');
 var plugins = require('../../plugins');
 var meta = require('../../meta');
-var utils = require('../../../public/src/utils');
+var utils = require('../../utils');
 
 var helpers = {};
 
diff --git a/src/controllers/admin/categories.js b/src/controllers/admin/categories.js
index 4a60fc14e2..3a3b1a6fa4 100644
--- a/src/controllers/admin/categories.js
+++ b/src/controllers/admin/categories.js
@@ -6,7 +6,7 @@ var categories = require('../../categories');
 var privileges = require('../../privileges');
 var analytics = require('../../analytics');
 var plugins = require('../../plugins');
-var translator = require('../../../public/src/modules/translator');
+var translator = require('../../translator');
 
 
 var categoriesController = {};
diff --git a/src/controllers/admin/settings.js b/src/controllers/admin/settings.js
index 55e5a1dfbf..7d1db3e73e 100644
--- a/src/controllers/admin/settings.js
+++ b/src/controllers/admin/settings.js
@@ -24,13 +24,13 @@ settingsController.get = function (req, res, next) {
 function renderEmail(req, res, next) {
 	var fs = require('fs');
 	var path = require('path');
-	var utils = require('../../../public/src/utils');
+	var file = require('../../file');
 
 	var emailsPath = path.join(nconf.get('views_dir'), 'emails');
 
 	async.waterfall([
 		function (next) {
-			utils.walk(emailsPath, next);
+			file.walk(emailsPath, next);
 		},
 		function (emails, next) {
 			async.map(emails, function (email, next) {
diff --git a/src/controllers/api.js b/src/controllers/api.js
index d0975c71fa..36f9355488 100644
--- a/src/controllers/api.js
+++ b/src/controllers/api.js
@@ -12,7 +12,7 @@ var categories = require('../categories');
 var privileges = require('../privileges');
 var plugins = require('../plugins');
 var widgets = require('../widgets');
-var translator = require('../../public/src/modules/translator');
+var translator = require('../translator');
 
 var apiController = module.exports;
 
diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js
index 6a2051d2c9..396aafd130 100644
--- a/src/controllers/authentication.js
+++ b/src/controllers/authentication.js
@@ -11,7 +11,7 @@ var db = require('../database');
 var meta = require('../meta');
 var user = require('../user');
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var Password = require('../password');
 
 var sockets = require('../socket.io');
diff --git a/src/controllers/category.js b/src/controllers/category.js
index ce5f7b5e07..88b49c0b24 100644
--- a/src/controllers/category.js
+++ b/src/controllers/category.js
@@ -11,7 +11,7 @@ var categories = require('../categories');
 var meta = require('../meta');
 var pagination = require('../pagination');
 var helpers = require('./helpers');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 var categoryController = {};
 
diff --git a/src/controllers/topics.js b/src/controllers/topics.js
index adfad461e2..4fe1bf96d5 100644
--- a/src/controllers/topics.js
+++ b/src/controllers/topics.js
@@ -13,7 +13,7 @@ var privileges = require('../privileges');
 var plugins = require('../plugins');
 var helpers = require('./helpers');
 var pagination = require('../pagination');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 var topicsController = {};
 
diff --git a/src/database/mongo/sorted.js b/src/database/mongo/sorted.js
index defaed80fc..59bd05b9fd 100644
--- a/src/database/mongo/sorted.js
+++ b/src/database/mongo/sorted.js
@@ -1,7 +1,7 @@
 'use strict';
 
 var async = require('async');
-var utils = require('../../../public/src/utils');
+var utils = require('../../utils');
 
 module.exports = function (db, module) {
 	var helpers = module.helpers.mongo;
diff --git a/src/database/redis/sorted.js b/src/database/redis/sorted.js
index a2c18296db..67f55bf343 100644
--- a/src/database/redis/sorted.js
+++ b/src/database/redis/sorted.js
@@ -1,7 +1,7 @@
 'use strict';
 
 module.exports = function (redisClient, module) {
-	var utils = require('../../../public/src/utils');
+	var utils = require('../../utils');
 
 	var helpers = module.helpers.redis;
 
diff --git a/src/emailer.js b/src/emailer.js
index 95ffbdceba..bad8f22650 100644
--- a/src/emailer.js
+++ b/src/emailer.js
@@ -13,7 +13,7 @@ var url = require('url');
 var User = require('./user');
 var Plugins = require('./plugins');
 var meta = require('./meta');
-var translator = require('../public/src/modules/translator');
+var translator = require('./translator');
 
 var transports = {
 	sendmail: nodemailer.createTransport(sendmailTransport()),
diff --git a/src/events.js b/src/events.js
index ab2864bc23..c7a8b26638 100644
--- a/src/events.js
+++ b/src/events.js
@@ -7,7 +7,7 @@ var validator = require('validator');
 var db = require('./database');
 var batch = require('./batch');
 var user = require('./user');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
 (function (events) {
 	events.log = function (data, callback) {
diff --git a/src/file.js b/src/file.js
index 78d428c41e..5a1e65a4b2 100644
--- a/src/file.js
+++ b/src/file.js
@@ -8,9 +8,9 @@ var jimp = require('jimp');
 var mkdirp = require('mkdirp');
 var mime = require('mime');
 
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
-var file = {};
+var file = module.exports;
 
 file.saveFileToLocal = function (filename, folder, tempPath, callback) {
 	/*
@@ -129,4 +129,47 @@ file.typeToExtension = function (type) {
 	return extension;
 };
 
+// Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search
+file.walk = function (dir, done) {
+	var results = [];
+
+	fs.readdir(dir, function (err, list) {
+		if (err) {
+			return done(err);
+		}
+		var pending = list.length;
+		if (!pending) {
+			return done(null, results);
+		}
+		list.forEach(function (filename) {
+			filename = dir + '/' + filename;
+			fs.stat(filename, function (err, stat) {
+				if (err) {
+					return done(err);
+				}
+
+				if (stat && stat.isDirectory()) {
+					file.walk(filename, function (err, res) {
+						if (err) {
+							return done(err);
+						}
+
+						results = results.concat(res);
+						pending -= 1;
+						if (!pending) {
+							done(null, results);
+						}
+					});
+				} else {
+					results.push(filename);
+					pending -= 1;
+					if (!pending) {
+						done(null, results);
+					}
+				}
+			});
+		});
+	});
+};
+
 module.exports = file;
diff --git a/src/groups.js b/src/groups.js
index fd8c4a958f..6462819e9e 100644
--- a/src/groups.js
+++ b/src/groups.js
@@ -6,7 +6,7 @@ var validator = require('validator');
 var user = require('./user');
 var db = require('./database');
 var plugins = require('./plugins');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
 var Groups = module.exports;
 
diff --git a/src/groups/create.js b/src/groups/create.js
index 4b680b8992..a14441608f 100644
--- a/src/groups/create.js
+++ b/src/groups/create.js
@@ -3,7 +3,7 @@
 var async = require('async');
 var meta = require('../meta');
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var db = require('../database');
 
 module.exports = function (Groups) {
diff --git a/src/groups/data.js b/src/groups/data.js
index 24e7f99a02..919a257368 100644
--- a/src/groups/data.js
+++ b/src/groups/data.js
@@ -5,7 +5,7 @@ var validator = require('validator');
 
 var db = require('../database');
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Groups) {
 	Groups.getGroupsData = function (groupNames, callback) {
diff --git a/src/groups/delete.js b/src/groups/delete.js
index 6aed7173a2..e05eff6370 100644
--- a/src/groups/delete.js
+++ b/src/groups/delete.js
@@ -2,7 +2,7 @@
 
 var async = require('async');
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var db = require('./../database');
 
 module.exports = function (Groups) {
diff --git a/src/groups/membership.js b/src/groups/membership.js
index 6bcafd2343..6337db1d8a 100644
--- a/src/groups/membership.js
+++ b/src/groups/membership.js
@@ -5,7 +5,7 @@ var winston = require('winston');
 var _ = require('underscore');
 
 var user = require('../user');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var plugins = require('../plugins');
 var notifications = require('../notifications');
 var db = require('../database');
diff --git a/src/groups/update.js b/src/groups/update.js
index 9bf53886e5..73104fd229 100644
--- a/src/groups/update.js
+++ b/src/groups/update.js
@@ -4,7 +4,7 @@ var async = require('async');
 var winston = require('winston');
 
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var db = require('../database');
 
 
diff --git a/src/install.js b/src/install.js
index a06a138f26..50e8328682 100644
--- a/src/install.js
+++ b/src/install.js
@@ -6,7 +6,7 @@ var path = require('path');
 var prompt = require('prompt');
 var winston = require('winston');
 var nconf = require('nconf');
-var utils = require('../public/src/utils.js');
+var utils = require('./utils.js');
 
 var install = {};
 var questions = {};
diff --git a/src/messaging.js b/src/messaging.js
index e141adff4f..aa16cd0b36 100644
--- a/src/messaging.js
+++ b/src/messaging.js
@@ -8,7 +8,7 @@ var db = require('./database');
 var user = require('./user');
 var plugins = require('./plugins');
 var meta = require('./meta');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
 var Messaging = module.exports;
 
diff --git a/src/messaging/data.js b/src/messaging/data.js
index e3cb67fbd8..3805b1c6f1 100644
--- a/src/messaging/data.js
+++ b/src/messaging/data.js
@@ -5,7 +5,7 @@ var S = require('string');
 
 var db = require('../database');
 var user = require('../user');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Messaging) {
 	Messaging.getMessageField = function (mid, field, callback) {
diff --git a/src/meta.js b/src/meta.js
index 6cbccd70a1..c67369a8d9 100644
--- a/src/meta.js
+++ b/src/meta.js
@@ -6,7 +6,7 @@ var os = require('os');
 var nconf = require('nconf');
 
 var pubsub = require('./pubsub');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
 (function (Meta) {
 	Meta.reloadRequired = false;
diff --git a/src/meta/css.js b/src/meta/css.js
index 33bd0877e0..88ad3348e8 100644
--- a/src/meta/css.js
+++ b/src/meta/css.js
@@ -13,7 +13,6 @@ var clean = require('postcss-clean');
 var plugins = require('../plugins');
 var db = require('../database');
 var file = require('../file');
-var utils = require('../../public/src/utils');
 
 module.exports = function (Meta) {
 	Meta.css = {};
@@ -106,7 +105,7 @@ module.exports = function (Meta) {
 		});
 
 		async.each(pluginDirectories, function (directory, next) {
-			utils.walk(directory, function (err, styleFiles) {
+			file.walk(directory, function (err, styleFiles) {
 				if (err) {
 					return next(err);
 				}
diff --git a/src/meta/js.js b/src/meta/js.js
index 72e41c578f..5efd5386cd 100644
--- a/src/meta/js.js
+++ b/src/meta/js.js
@@ -11,7 +11,6 @@ var uglifyjs = require('uglify-js');
 
 var file = require('../file');
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
 
 var minifierPath = path.join(__dirname, 'minifier.js');
 
@@ -168,7 +167,7 @@ module.exports = function (Meta) {
 		});
 
 		async.each(dirs, function (dir, next) {
-			utils.walk(dir, function (err, files) {
+			file.walk(dir, function (err, files) {
 				if (err) {
 					return next(err);
 				}
@@ -293,7 +292,7 @@ module.exports = function (Meta) {
 		});
 
 		async.each(pluginDirectories, function (directory, next) {
-			utils.walk(directory, function (err, scripts) {
+			file.walk(directory, function (err, scripts) {
 				pluginsScripts = pluginsScripts.concat(scripts);
 				next(err);
 			});
diff --git a/src/meta/languages.js b/src/meta/languages.js
index 67bd9fabd5..b420445f16 100644
--- a/src/meta/languages.js
+++ b/src/meta/languages.js
@@ -8,7 +8,6 @@ var mkdirp = require('mkdirp');
 var rimraf = require('rimraf');
 
 var file = require('../file');
-var utils = require('../../public/src/utils');
 var Plugins = require('../plugins');
 var db = require('../database');
 
@@ -67,7 +66,7 @@ function getTranslationTree(callback) {
 			async.parallel([
 				// get core languages and namespaces
 				function (nxt) {
-					utils.walk(coreLanguagesPath, function (err, paths) {
+					file.walk(coreLanguagesPath, function (err, paths) {
 						if (err) {
 							return nxt(err);
 						}
@@ -80,7 +79,7 @@ function getTranslationTree(callback) {
 				function (nxt) {
 					async.each(plugins, function (pluginData, cb) {
 						var pathToFolder = path.join(__dirname, '../../node_modules/', pluginData.id, pluginData.languages);
-						utils.walk(pathToFolder, function (err, paths) {
+						file.walk(pathToFolder, function (err, paths) {
 							if (err) {
 								return cb(err);
 							}
diff --git a/src/meta/templates.js b/src/meta/templates.js
index 21b5889d26..9420959694 100644
--- a/src/meta/templates.js
+++ b/src/meta/templates.js
@@ -9,7 +9,7 @@ var fs = require('fs');
 var nconf = require('nconf');
 
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var file = require('../file');
 
 var Templates = {};
 
@@ -62,11 +62,11 @@ function preparePaths(baseTemplatesPaths, callback) {
 
 		async.parallel({
 			coreTpls: function (next) {
-				utils.walk(coreTemplatesPath, next);
+				file.walk(coreTemplatesPath, next);
 			},
 			baseThemes: function (next) {
 				async.map(baseTemplatesPaths, function (baseTemplatePath, next) {
-					utils.walk(baseTemplatePath, function (err, paths) {
+					file.walk(baseTemplatePath, function (err, paths) {
 						paths = paths.map(function (tpl) {
 							return {
 								base: baseTemplatePath,
diff --git a/src/middleware/render.js b/src/middleware/render.js
index 88e9879887..366f6f9f2a 100644
--- a/src/middleware/render.js
+++ b/src/middleware/render.js
@@ -6,7 +6,7 @@ var validator = require('validator');
 var winston = require('winston');
 
 var plugins = require('../plugins');
-var translator = require('../../public/src/modules/translator');
+var translator = require('../translator');
 
 module.exports = function (middleware) {
 	middleware.processRender = function (req, res, next) {
diff --git a/src/navigation/admin.js b/src/navigation/admin.js
index 0917e9e524..6b0984a466 100644
--- a/src/navigation/admin.js
+++ b/src/navigation/admin.js
@@ -3,7 +3,7 @@
 var async = require('async');
 var plugins = require('../plugins');
 var db = require('../database');
-var translator = require('../../public/src/modules/translator');
+var translator = require('../translator');
 var pubsub = require('../pubsub');
 
 var admin = module.exports;
diff --git a/src/navigation/index.js b/src/navigation/index.js
index 2cb24f3a9f..76b0ceeceb 100644
--- a/src/navigation/index.js
+++ b/src/navigation/index.js
@@ -2,7 +2,7 @@
 
 var nconf = require('nconf');
 var admin = require('./admin');
-var translator = require('../../public/src/modules/translator');
+var translator = require('../translator');
 
 var navigation = {};
 
diff --git a/src/notifications.js b/src/notifications.js
index 31960dc2f1..147ae7fea4 100644
--- a/src/notifications.js
+++ b/src/notifications.js
@@ -13,7 +13,7 @@ var groups = require('./groups');
 var meta = require('./meta');
 var batch = require('./batch');
 var plugins = require('./plugins');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
 (function (Notifications) {
 	Notifications.init = function () {
diff --git a/src/plugins.js b/src/plugins.js
index 7c2ecaee25..e4f1fa8312 100644
--- a/src/plugins.js
+++ b/src/plugins.js
@@ -9,7 +9,6 @@ var express = require('express');
 var nconf = require('nconf');
 
 var db = require('./database');
-var utils = require('../public/src/utils');
 var hotswap = require('./hotswap');
 var file = require('./file');
 var languages = require('./languages');
@@ -176,7 +175,7 @@ var middleware;
 				if (plugin.templates || plugin.id.startsWith('nodebb-theme-')) {
 					winston.verbose('[plugins] Loading templates (' + plugin.id + ')');
 					var templatesPath = path.join(__dirname, '../node_modules', plugin.id, plugin.templates || 'templates');
-					utils.walk(templatesPath, function (err, pluginTemplates) {
+					file.walk(templatesPath, function (err, pluginTemplates) {
 						if (pluginTemplates) {
 							pluginTemplates.forEach(function (pluginTemplate) {
 								if (pluginTemplate.endsWith('.tpl')) {
diff --git a/src/posts.js b/src/posts.js
index c7e7ec3e0a..4b9febae07 100644
--- a/src/posts.js
+++ b/src/posts.js
@@ -4,7 +4,7 @@ var async = require('async');
 var _ = require('underscore');
 
 var db = require('./database');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 var user = require('./user');
 var topics = require('./topics');
 var privileges = require('./privileges');
diff --git a/src/posts/create.js b/src/posts/create.js
index e8e24a5585..86faf0ffa9 100644
--- a/src/posts/create.js
+++ b/src/posts/create.js
@@ -9,7 +9,7 @@ var plugins = require('../plugins');
 var user = require('../user');
 var topics = require('../topics');
 var categories = require('../categories');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Posts) {
 	Posts.create = function (data, callback) {
diff --git a/src/posts/edit.js b/src/posts/edit.js
index 863888a6ce..3e9d295f19 100644
--- a/src/posts/edit.js
+++ b/src/posts/edit.js
@@ -11,7 +11,7 @@ var privileges = require('../privileges');
 var plugins = require('../plugins');
 var cache = require('./cache');
 var pubsub = require('../pubsub');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Posts) {
 	pubsub.on('post:edit', function (pid) {
diff --git a/src/posts/parse.js b/src/posts/parse.js
index 8ac2028bbd..e5ce10e1ac 100644
--- a/src/posts/parse.js
+++ b/src/posts/parse.js
@@ -9,7 +9,7 @@ var S = require('string');
 var meta = require('../meta');
 var cache = require('./cache');
 var plugins = require('../plugins');
-var translator = require('../../public/src/modules/translator');
+var translator = require('../translator');
 
 var urlRegex = /href="([^"]+)"/g;
 
diff --git a/src/posts/summary.js b/src/posts/summary.js
index 93e322229d..a05718b95c 100644
--- a/src/posts/summary.js
+++ b/src/posts/summary.js
@@ -9,7 +9,7 @@ var db = require('../database');
 var user = require('../user');
 var plugins = require('../plugins');
 var categories = require('../categories');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 
 module.exports = function (Posts) {
diff --git a/src/posts/topics.js b/src/posts/topics.js
index eca6da493a..219be7b0d3 100644
--- a/src/posts/topics.js
+++ b/src/posts/topics.js
@@ -4,7 +4,7 @@
 var async = require('async');
 
 var topics = require('../topics');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Posts) {
 	Posts.getPostsFromSet = function (set, start, stop, uid, reverse, callback) {
diff --git a/src/search.js b/src/search.js
index ffe33c8ef5..e223e3ea14 100644
--- a/src/search.js
+++ b/src/search.js
@@ -10,7 +10,7 @@ var categories = require('./categories');
 var user = require('./user');
 var plugins = require('./plugins');
 var privileges = require('./privileges');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
 var search = {};
 
diff --git a/src/sitemap.js b/src/sitemap.js
index d6f6fa39fe..d828f9d784 100644
--- a/src/sitemap.js
+++ b/src/sitemap.js
@@ -10,7 +10,7 @@ var topics = require('./topics');
 var privileges = require('./privileges');
 var meta = require('./meta');
 var plugins = require('./plugins');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 
 var sitemap = {
 	maps: {
diff --git a/src/socket.io/groups.js b/src/socket.io/groups.js
index ed6cb00180..f9f6c1b263 100644
--- a/src/socket.io/groups.js
+++ b/src/socket.io/groups.js
@@ -5,7 +5,7 @@ var async = require('async');
 var groups = require('../groups');
 var meta = require('../meta');
 var user = require('../user');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var groupsController = require('../controllers/groups');
 
 var SocketGroups = {};
diff --git a/src/socket.io/modules.js b/src/socket.io/modules.js
index f0309e8d30..4480a9d0f7 100644
--- a/src/socket.io/modules.js
+++ b/src/socket.io/modules.js
@@ -7,7 +7,7 @@ var meta = require('../meta');
 var notifications = require('../notifications');
 var plugins = require('../plugins');
 var Messaging = require('../messaging');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var server = require('./');
 var user = require('../user');
 
diff --git a/src/socket.io/notifications.js b/src/socket.io/notifications.js
index 66e5135ed6..af47782d5d 100644
--- a/src/socket.io/notifications.js
+++ b/src/socket.io/notifications.js
@@ -3,7 +3,7 @@
 var async = require('async');
 var user = require('../user');
 var notifications = require('../notifications');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 var SocketNotifs = {};
 
diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js
index b4b5ac40cd..e98052a2f9 100644
--- a/src/socket.io/posts.js
+++ b/src/socket.io/posts.js
@@ -9,7 +9,7 @@ var topics = require('../topics');
 var user = require('../user');
 var websockets = require('./index');
 var socketHelpers = require('./helpers');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 var apiController = require('../controllers/api');
 
diff --git a/src/socket.io/posts/flag.js b/src/socket.io/posts/flag.js
index dccf302c43..1464c6ac93 100644
--- a/src/socket.io/posts/flag.js
+++ b/src/socket.io/posts/flag.js
@@ -11,7 +11,7 @@ var privileges = require('../../privileges');
 var notifications = require('../../notifications');
 var plugins = require('../../plugins');
 var meta = require('../../meta');
-var utils = require('../../../public/src/utils');
+var utils = require('../../utils');
 
 module.exports = function (SocketPosts) {
 	SocketPosts.flag = function (socket, data, callback) {
diff --git a/src/socket.io/topics/infinitescroll.js b/src/socket.io/topics/infinitescroll.js
index b0d7407a0a..87b27a6561 100644
--- a/src/socket.io/topics/infinitescroll.js
+++ b/src/socket.io/topics/infinitescroll.js
@@ -5,7 +5,7 @@ var async = require('async');
 var topics = require('../../topics');
 var privileges = require('../../privileges');
 var meta = require('../../meta');
-var utils = require('../../../public/src/utils');
+var utils = require('../../utils');
 var social = require('../../social');
 
 module.exports = function (SocketTopics) {
diff --git a/src/socket.io/topics/tags.js b/src/socket.io/topics/tags.js
index 0b7076fa20..fd0c0d0987 100644
--- a/src/socket.io/topics/tags.js
+++ b/src/socket.io/topics/tags.js
@@ -3,7 +3,7 @@
 var async = require('async');
 var db = require('../../database');
 var topics = require('../../topics');
-var utils = require('../../../public/src/utils');
+var utils = require('../../utils');
 
 module.exports = function (SocketTopics) {
 	SocketTopics.isTagAllowed = function (socket, data, callback) {
diff --git a/src/topics.js b/src/topics.js
index ed7deacc2e..12632193fb 100644
--- a/src/topics.js
+++ b/src/topics.js
@@ -5,7 +5,7 @@ var _ = require('underscore');
 
 var db = require('./database');
 var posts = require('./posts');
-var utils = require('../public/src/utils');
+var utils = require('./utils');
 var plugins = require('./plugins');
 var user = require('./user');
 var categories = require('./categories');
diff --git a/src/topics/create.js b/src/topics/create.js
index da16489f05..294b241d39 100644
--- a/src/topics/create.js
+++ b/src/topics/create.js
@@ -5,7 +5,7 @@ var async = require('async');
 var validator = require('validator');
 var S = require('string');
 var db = require('../database');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var plugins = require('../plugins');
 var analytics = require('../analytics');
 var user = require('../user');
diff --git a/src/topics/data.js b/src/topics/data.js
index 17e060f679..8df112dcbf 100644
--- a/src/topics/data.js
+++ b/src/topics/data.js
@@ -4,7 +4,7 @@ var validator = require('validator');
 
 var db = require('../database');
 var categories = require('../categories');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Topics) {
 	Topics.getTopicField = function (tid, field, callback) {
diff --git a/src/topics/tags.js b/src/topics/tags.js
index d10c127ac0..d2f2b32694 100644
--- a/src/topics/tags.js
+++ b/src/topics/tags.js
@@ -7,7 +7,7 @@ var db = require('../database');
 var meta = require('../meta');
 var _ = require('underscore');
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 
 module.exports = function (Topics) {
diff --git a/src/topics/teaser.js b/src/topics/teaser.js
index b990b608d1..f864e3e23d 100644
--- a/src/topics/teaser.js
+++ b/src/topics/teaser.js
@@ -9,7 +9,7 @@ var meta = require('../meta');
 var user = require('../user');
 var posts = require('../posts');
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Topics) {
 	Topics.getTeasers = function (topics, uid, callback) {
diff --git a/src/topics/unread.js b/src/topics/unread.js
index b2f5b199d1..e089fdaad9 100644
--- a/src/topics/unread.js
+++ b/src/topics/unread.js
@@ -9,7 +9,7 @@ var notifications = require('../notifications');
 var categories = require('../categories');
 var privileges = require('../privileges');
 var meta = require('../meta');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (Topics) {
 	Topics.getTotalUnread = function (uid, filter, callback) {
diff --git a/src/translator.js b/src/translator.js
new file mode 100644
index 0000000000..21d4891332
--- /dev/null
+++ b/src/translator.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('../public/src/modules/translator');
diff --git a/src/user/approval.js b/src/user/approval.js
index cbb1ba08b4..23d24a1e16 100644
--- a/src/user/approval.js
+++ b/src/user/approval.js
@@ -9,8 +9,8 @@ var meta = require('../meta');
 var emailer = require('../emailer');
 var notifications = require('../notifications');
 var groups = require('../groups');
-var translator = require('../../public/src/modules/translator');
-var utils = require('../../public/src/utils');
+var translator = require('../translator');
+var utils = require('../utils');
 var plugins = require('../plugins');
 
 module.exports = function (User) {
diff --git a/src/user/create.js b/src/user/create.js
index 7d5e56f96f..e9cda9bce2 100644
--- a/src/user/create.js
+++ b/src/user/create.js
@@ -2,7 +2,7 @@
 
 var async = require('async');
 var db = require('../database');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var validator = require('validator');
 var plugins = require('../plugins');
 var groups = require('../groups');
diff --git a/src/user/data.js b/src/user/data.js
index 120da7e3a2..d0504ffce6 100644
--- a/src/user/data.js
+++ b/src/user/data.js
@@ -7,7 +7,7 @@ var winston = require('winston');
 
 var db = require('../database');
 var plugins = require('../plugins');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 module.exports = function (User) {
 	var iconBackgrounds = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3',
diff --git a/src/user/digest.js b/src/user/digest.js
index 73cd773713..bf11e23a65 100644
--- a/src/user/digest.js
+++ b/src/user/digest.js
@@ -10,7 +10,7 @@ var user = require('../user');
 var topics = require('../topics');
 var plugins = require('../plugins');
 var emailer = require('../emailer');
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 
 (function (Digest) {
 	Digest.execute = function (interval, callback) {
diff --git a/src/user/email.js b/src/user/email.js
index 8b8919c73a..d0cdbbed3c 100644
--- a/src/user/email.js
+++ b/src/user/email.js
@@ -5,8 +5,8 @@ var async = require('async');
 var nconf = require('nconf');
 
 var user = require('../user');
-var utils = require('../../public/src/utils');
-var translator = require('../../public/src/modules/translator');
+var utils = require('../utils');
+var translator = require('../translator');
 var plugins = require('../plugins');
 var db = require('../database');
 var meta = require('../meta');
diff --git a/src/user/invite.js b/src/user/invite.js
index 4e41b824a5..b7d62bdc7b 100644
--- a/src/user/invite.js
+++ b/src/user/invite.js
@@ -7,8 +7,8 @@ var nconf = require('nconf');
 var db = require('./../database');
 var meta = require('../meta');
 var emailer = require('../emailer');
-var translator = require('../../public/src/modules/translator');
-var utils = require('../../public/src/utils');
+var translator = require('../translator');
+var utils = require('../utils');
 
 
 module.exports = function (User) {
diff --git a/src/user/profile.js b/src/user/profile.js
index b2b3b7eb5f..e6ac5adf0f 100644
--- a/src/user/profile.js
+++ b/src/user/profile.js
@@ -4,7 +4,7 @@
 var async = require('async');
 var S = require('string');
 
-var utils = require('../../public/src/utils');
+var utils = require('../utils');
 var meta = require('../meta');
 var db = require('../database');
 var groups = require('../groups');
diff --git a/src/user/reset.js b/src/user/reset.js
index ba0e18b513..25bd4118f9 100644
--- a/src/user/reset.js
+++ b/src/user/reset.js
@@ -5,8 +5,8 @@ var nconf = require('nconf');
 var winston = require('winston');
 
 var user = require('../user');
-var utils = require('../../public/src/utils');
-var translator = require('../../public/src/modules/translator');
+var utils = require('../utils');
+var translator = require('../translator');
 
 var db = require('../database');
 var meta = require('../meta');
diff --git a/src/utils.js b/src/utils.js
new file mode 100644
index 0000000000..8913909584
--- /dev/null
+++ b/src/utils.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('../public/src/utils');
diff --git a/src/widgets/index.js b/src/widgets/index.js
index 7ea6727a1e..2e439c52d8 100644
--- a/src/widgets/index.js
+++ b/src/widgets/index.js
@@ -5,7 +5,7 @@ var winston = require('winston');
 var templates = require('templates.js');
 
 var plugins = require('../plugins');
-var translator = require('../../public/src/modules/translator');
+var translator = require('../translator');
 var db = require('../database');
 
 var widgets = {};

From 18924925058bbafad06370bfa33984aecd6191d0 Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak <p.jaszkow@gmail.com>
Date: Sat, 8 Apr 2017 21:02:06 -0600
Subject: [PATCH 2/2] Deprecate utils.walk, remove prototype modification

---
 public/src/utils.js  | 10 ++++------
 src/topics/create.js |  8 ++++++--
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/public/src/utils.js b/public/src/utils.js
index 622b8281a9..16a5bdbef7 100644
--- a/public/src/utils.js
+++ b/public/src/utils.js
@@ -2,9 +2,13 @@
 
 (function (factory) {
 	if (typeof module === 'object' && module.exports) {
+		var winston = require('winston');
+
 		var file = require('../../src/file');
 		module.exports = factory(require('xregexp'));
 		module.exports.walk = function (dir, done) {
+			// DEPRECATED
+			winston.warn('[deprecated] `utils.walk` is deprecated. Use `file.walk` instead.');
 			file.walk(dir, done);
 		};
 
@@ -424,11 +428,5 @@
 		};
 	}
 
-	if (typeof String.prototype.rtrim !== 'function') {
-		String.prototype.rtrim = function () {
-			return this.replace(/\s+$/g, '');
-		};
-	}
-
 	return utils;
 }));
diff --git a/src/topics/create.js b/src/topics/create.js
index 294b241d39..2c7f87741b 100644
--- a/src/topics/create.js
+++ b/src/topics/create.js
@@ -87,6 +87,10 @@ module.exports = function (Topics) {
 		], callback);
 	};
 
+	function rtrim(str) {
+		return str.replace(/\s+$/g, '');
+	}
+
 	Topics.post = function (data, callback) {
 		var uid = data.uid;
 		data.title = String(data.title).trim();
@@ -101,7 +105,7 @@ module.exports = function (Topics) {
 			},
 			function (next) {
 				if (data.content) {
-					data.content = data.content.rtrim();
+					data.content = rtrim(data.content);
 				}
 				check(data.content, meta.config.minimumPostLength, meta.config.maximumPostLength, 'content-too-short', 'content-too-long', next);
 			},
@@ -234,7 +238,7 @@ module.exports = function (Topics) {
 			function (filteredData, next) {
 				content = filteredData.content || data.content;
 				if (content) {
-					content = content.rtrim();
+					content = rtrim(content);
 				}
 
 				check(content, meta.config.minimumPostLength, meta.config.maximumPostLength, 'content-too-short', 'content-too-long', next);