diff --git a/src/controllers/uploads.js b/src/controllers/uploads.js new file mode 100644 index 0000000000..237ae5c453 --- /dev/null +++ b/src/controllers/uploads.js @@ -0,0 +1,125 @@ +"use strict"; + +var uploadsController = {}, + + fs = require('fs'), + path = require('path'), + async = require('async'), + + meta = require('../meta'), + plugins = require('../plugins'), + utils = require('../../public/src/utils'), + image = require('../image'); + + +uploadsController.upload = function(req, res, filesIterator, next) { + var files = req.files.files; + + if (!req.user) { + deleteTempFiles(files); + return res.status(403).json('not allowed'); + } + + if (!Array.isArray(files)) { + return res.status(500).json('invalid files'); + } + + if (Array.isArray(files[0])) { + files = files[0]; + } + + async.map(files, filesIterator, function(err, images) { + deleteTempFiles(files); + + if (err) { + return res.status(500).send(err.message); + } + + // IE8 - send it as text/html so browser won't trigger a file download for the json response + // malsup.com/jquery/form/#file-upload + res.status(200).send(req.xhr ? images : JSON.stringify(images)); + }); +}; + +uploadsController.uploadPost = function(req, res, next) { + uploadsController.upload(req, res, function(file, next) { + if (file.type.match(/image./)) { + uploadImage(req.user.uid, file, next); + } else { + uploadFile(req.user.uid, file, next); + } + }, next); +}; + +uploadsController.uploadThumb = function(req, res, next) { + if (parseInt(meta.config.allowTopicsThumbnail, 10) !== 1) { + deleteTempFiles(req.files.files); + return next(new Error('[[error:topic-thumbnails-are-disabled]]')); + } + + uploadsController.upload(req, res, function(file, next) { + if(file.type.match(/image./)) { + var size = meta.config.topicThumbSize || 120; + image.resizeImage(file.path, path.extname(file.name), size, size, function(err) { + if (err) { + return next(err); + } + uploadImage(req.user.uid, file, next); + }); + } else { + next(new Error('[[error:invalid-file]]')); + } + }, next); +}; + +function uploadImage(uid, image, callback) { + if (plugins.hasListeners('filter:uploadImage')) { + return plugins.fireHook('filter:uploadImage', {image: image, uid: uid}, callback); + } + + if (parseInt(meta.config.allowFileUploads, 10)) { + uploadFile(uid, image, callback); + } else { + callback(new Error('[[error:uploads-are-disabled]]')); + } +} + +function uploadFile(uid, file, callback) { + if (plugins.hasListeners('filter:uploadFile')) { + return plugins.fireHook('filter:uploadFile', {file: file, uid: uid}, callback); + } + + if (parseInt(meta.config.allowFileUploads, 10) !== 1) { + return callback(new Error('[[error:uploads-are-disabled]]')); + } + + if (!file) { + return callback(new Error('[[error:invalid-file]]')); + } + + if (file.size > parseInt(meta.config.maximumFileSize, 10) * 1024) { + return callback(new Error('[[error:file-too-big, ' + meta.config.maximumFileSize + ']]')); + } + + var filename = 'upload-' + utils.generateUUID() + path.extname(file.name); + require('../file').saveFileToLocal(filename, 'files', file.path, function(err, upload) { + if (err) { + return callback(err); + } + + callback(null, { + url: upload.url, + name: file.name + }); + }); +} + +function deleteTempFiles(files) { + for(var i=0; i parseInt(meta.config.maximumFileSize, 10) * 1024) { - return callback(new Error('[[error:file-too-big, ' + meta.config.maximumFileSize + ']]')); - } + router.get('/config', middleware.applyCSRF, controllers.api.getConfig); + router.get('/widgets/render', controllers.api.renderWidgets); - var filename = 'upload-' + utils.generateUUID() + path.extname(file.name); - require('../file').saveFileToLocal(filename, 'files', file.path, function(err, upload) { - if(err) { - return callback(err); - } + router.get('/user/uid/:uid', middleware.checkGlobalPrivacySettings, controllers.accounts.getUserByUID); + router.get('/get_templates_listing', getTemplatesListing); + router.get('/categories/:cid/moderators', getModerators); + router.get('/recent/posts/:term?', getRecentPosts); - callback(null, { - url: upload.url, - name: file.name - }); - }); - } -} + var multipart = require('connect-multiparty'); + var multipartMiddleware = multipart(); + router.post('/post/upload', multipartMiddleware, middleware.applyCSRF, uploadsController.uploadPost); + router.post('/topic/thumb/upload', multipartMiddleware, middleware.applyCSRF, uploadsController.uploadThumb); + router.post('/user/:userslug/uploadpicture', multipartMiddleware, middleware.applyCSRF, middleware.authenticate, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.uploadPicture); +}; function getModerators(req, res, next) { categories.getModerators(req.params.cid, function(err, moderators) { @@ -196,26 +101,4 @@ function getRecentPosts(req, res, next) { res.json(data); }); -} - -module.exports = function(app, middleware, controllers) { - - var router = express.Router(); - app.use('/api', router); - - router.get('/config', middleware.applyCSRF, controllers.api.getConfig); - router.get('/widgets/render', controllers.api.renderWidgets); - - router.get('/user/uid/:uid', middleware.checkGlobalPrivacySettings, controllers.accounts.getUserByUID); - router.get('/get_templates_listing', getTemplatesListing); - router.get('/categories/:cid/moderators', getModerators); - router.get('/recent/posts/:term?', getRecentPosts); - - var multipart = require('connect-multiparty'); - var multipartMiddleware = multipart(); - - router.post('/post/upload', multipartMiddleware, middleware.applyCSRF, uploadPost); - router.post('/topic/thumb/upload', multipartMiddleware, middleware.applyCSRF, uploadThumb); - router.post('/user/:userslug/uploadpicture', multipartMiddleware, middleware.applyCSRF, middleware.authenticate, middleware.checkGlobalPrivacySettings, middleware.checkAccountPermissions, controllers.accounts.uploadPicture); - -}; +} \ No newline at end of file