diff --git a/public/src/modules/composer.js b/public/src/modules/composer.js index 7496c5c257..017edbbdb9 100644 --- a/public/src/modules/composer.js +++ b/public/src/modules/composer.js @@ -115,7 +115,7 @@ define(['taskbar'], function(taskbar) { var postContainer = $(composerTemplate[0]); - if(config.allowFileUploads || config.hasPostUploadPlugin) { + if(config.allowFileUploads || config.hasImageUploadPlugin) { initializeFileReader(post_uuid); } @@ -369,7 +369,7 @@ define(['taskbar'], function(taskbar) { postContainer.css('height', $(window).height() - $('#header-menu').height()); } - if(config.hasPostUploadPlugin) { + if(config.hasImageUploadPlugin) { if(env === 'md' || env === 'lg') { postContainer.find('.upload-instructions').removeClass('hide'); } diff --git a/src/posts.js b/src/posts.js index f33427fc88..7bd44f72d1 100644 --- a/src/posts.js +++ b/src/posts.js @@ -396,8 +396,8 @@ var db = require('./database'), Posts.uploadPostImage = function(image, callback) { - if(plugins.hasListeners('filter:post.uploadImage')) { - plugins.fireHook('filter:post.uploadImage', image, callback); + if(plugins.hasListeners('filter:uploadImage')) { + plugins.fireHook('filter:uploadImage', image, callback); } else { if (meta.config.allowFileUploads) { @@ -410,8 +410,8 @@ var db = require('./database'), Posts.uploadPostFile = function(file, callback) { - if(plugins.hasListeners('filter:post.uploadFile')) { - plugins.fireHook('filter:post.uploadFile', file, callback); + if(plugins.hasListeners('filter:uploadFile')) { + plugins.fireHook('filter:uploadFile', file, callback); } else { if(!meta.config.allowFileUploads) { diff --git a/src/routes/admin.js b/src/routes/admin.js index a1db542d34..b65c4af9fd 100644 --- a/src/routes/admin.js +++ b/src/routes/admin.js @@ -11,6 +11,7 @@ var nconf = require('nconf'), categories = require('./../categories'), meta = require('../meta'), plugins = require('../plugins'), + image = require('./../image'), Languages = require('../languages'), events = require('./../events'), utils = require('./../../public/src/utils'), @@ -139,7 +140,17 @@ var nconf = require('nconf'), return; } - uploadImage('favicon.ico', req, res); + saveFileToLocal('favicon.ico', req, res, function(err, image) { + if(err) { + return res.send({ + error: err.message + }); + } + + res.json({ + path: image.url + }); + }); }); app.post('/uploadlogo', function(req, res) { @@ -156,7 +167,7 @@ var nconf = require('nconf'), return; } - var filename = 'site-logo' + path.extname(req.files.userPhoto.name); + var filename = 'site-logo' + path.extname(req.files.userPhoto.name); uploadImage(filename, req, res); }); @@ -171,6 +182,32 @@ var nconf = require('nconf'), }); function uploadImage(filename, req, res) { + function done(err, image) { + if(err) { + return res.send({ + error: err.message + }); + } + + res.json({ + path: image.url + }); + } + + if(plugins.hasListeners('filter:uploadImage')) { + image.convertImageToBase64(req.files.userPhoto.path, function(err, image64) { + if(err) { + return done(err); + } + + plugins.fireHook('filter:uploadImage', {data:image64, name:filename}, done); + }); + } else { + saveFileToLocal(filename, req, res, done); + } + } + + function saveFileToLocal(filename, req, res, callback) { var tempPath = req.files.userPhoto.path; var extension = path.extname(req.files.userPhoto.name); @@ -191,9 +228,7 @@ var nconf = require('nconf'), is.on('end', function () { fs.unlinkSync(tempPath); - res.json({ - path: nconf.get('upload_url') + filename - }); + callback(null, {url: nconf.get('upload_url') + filename}); }); os.on('error', function (err) { @@ -204,7 +239,6 @@ var nconf = require('nconf'), is.pipe(os); } - var custom_routes = { 'routes': [], 'api': [] diff --git a/src/routes/api.js b/src/routes/api.js index 89e16cf268..bb27b2c199 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -37,7 +37,7 @@ var path = require('path'), config.minimumTitleLength = meta.config.minimumTitleLength; config.maximumTitleLength = meta.config.maximumTitleLength; config.minimumPostLength = meta.config.minimumPostLength; - config.hasPostUploadPlugin = Plugins.hasListeners('filter:post.uploadImage'); + config.hasImageUploadPlugin = Plugins.hasListeners('filter:uploadImage'); config.minimumUsernameLength = meta.config.minimumUsernameLength; config.maximumUsernameLength = meta.config.maximumUsernameLength; config.minimumPasswordLength = meta.config.minimumPasswordLength; diff --git a/src/routes/user.js b/src/routes/user.js index 9fee9d62c5..147fff2ef1 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -3,6 +3,7 @@ var fs = require('fs'), winston = require('winston'), nconf = require('nconf'), async= require('async'), + imagemagick = require('node-imagemagick'), user = require('./../user'), posts = require('./../posts'), @@ -10,6 +11,8 @@ var fs = require('fs'), utils = require('./../../public/src/utils'), templates = require('./../../public/src/templates'), meta = require('./../meta'), + plugins = require('./../plugins'), + image = require('./../image'), db = require('./../database'); (function (User) { @@ -114,118 +117,101 @@ var fs = require('fs'), }); app.post('/uploadpicture', function (req, res) { - if (!req.user) - return res.redirect('/403'); + if (!req.user) { + return res.json(403, { + error: 'Not allowed!' + }); + } var uploadSize = parseInt(meta.config.maximumProfileImageSize, 10) || 256; - if (req.files.userPhoto.size > uploadSize * 1024) { - res.send({ + return res.send({ error: 'Images must be smaller than ' + uploadSize + ' kb!' }); - return; } var allowedTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif']; - if (allowedTypes.indexOf(req.files.userPhoto.type) === -1) { - res.send({ + return res.send({ error: 'Allowed image types are png, jpg and gif!' }); - return; } - user.getUserField(req.user.uid, 'uploadedpicture', function (err, oldpicture) { - if (!oldpicture) { - uploadUserPicture(req.user.uid, path.extname(req.files.userPhoto.name), req.files.userPhoto.path, res); - return; - } + var extension = path.extname(req.files.userPhoto.name); + if (!extension) { + return res.send({ + error: 'Error uploading file! Error : Invalid extension!' + }); + } - var absolutePath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), path.basename(oldpicture)); + var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10); + var filename = req.user.uid + '-profileimg' + (convertToPNG ? '.png' : extension); - fs.unlink(absolutePath, function (err) { - if (err) { - winston.err(err); + async.waterfall([ + function(next) { + image.resizeImage(req.files.userPhoto.path, extension, 128, 128, next); + }, + function(next) { + image.convertImageToPng(req.files.userPhoto.path, extension, next); + } + ], function(err, result) { + function done(err, image) { + if(err) { + return res.send({error: err.message}); } - uploadUserPicture(req.user.uid, path.extname(req.files.userPhoto.name), req.files.userPhoto.path, res); - }); + user.setUserField(req.user.uid, 'uploadedpicture', image.url); + user.setUserField(req.user.uid, 'picture', image.url); + res.json({ + path: image.url + }); + } + + if(err) { + return res.send({error:err.message}); + } + + if(plugins.hasListeners('filter:uploadImage')) { + image.convertImageToBase64(req.files.userPhoto.path, function(err, image64) { + plugins.fireHook('filter:uploadImage', {data:image64, name:filename}, done); + }); + } else { + + user.getUserField(req.user.uid, 'uploadedpicture', function (err, oldpicture) { + if (!oldpicture) { + saveFileToLocal(filename, req.files.userPhoto.path, done); + return; + } + + var absolutePath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), path.basename(oldpicture)); + + fs.unlink(absolutePath, function (err) { + if (err) { + winston.err(err); + } + + saveFileToLocal(filename, req.files.userPhoto.path, done); + }); + }); + } }); }); }); - function uploadUserPicture(uid, extension, tempPath, res) { - if (!extension) { - res.send({ - error: 'Error uploading file! Error : Invalid extension!' - }); - return; - } - var convertToPNG = parseInt(meta.config['profile:convertProfileImageToPNG'], 10); + function saveFileToLocal(filename, tempPath, callback) { - var filename = uid + '-profileimg' + (convertToPNG ? '.png' : extension); var uploadPath = path.join(nconf.get('base_dir'), nconf.get('upload_path'), filename); - winston.info('Attempting upload to: ' + uploadPath); + winston.info('Saving file '+ filename +' to : ' + uploadPath); var is = fs.createReadStream(tempPath); var os = fs.createWriteStream(uploadPath); - var im = require('node-imagemagick'); is.on('end', function () { fs.unlinkSync(tempPath); - function done(err) { - if (err) { - winston.err(err); - res.send({ - error: 'Invalid image file!' - }); - return; - } - - var imageUrl = nconf.get('upload_url') + filename; - - user.setUserField(uid, 'uploadedpicture', imageUrl); - user.setUserField(uid, 'picture', imageUrl); - - if (convertToPNG && extension !== '.png') { - im.convert([uploadPath, 'png:-'], function(err, stdout) { - if (err) { - winston.err(err); - res.send({ - error: 'Unable to convert image to PNG.' - }); - return; - } - - fs.writeFileSync(uploadPath, stdout, 'binary'); - res.json({ - path: imageUrl - }); - }); - } else { - res.json({ - path: imageUrl - }); - } - } - - if(extension === '.gif') { - im.convert([uploadPath, '-coalesce', '-repage', '0x0', '-crop', '128x128+0+0', '+repage', 'uploadPath'], function(err, stdout) { - done(err); - }); - } else { - im.crop({ - srcPath: uploadPath, - dstPath: uploadPath, - width: 128, - height: 128 - }, function (err, stdout, stderr) { - done(err); - }); - } + callback(null, {url: nconf.get('upload_url') + filename}); }); os.on('error', function (err) {