mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 19:15:58 +01:00 
			
		
		
		
	feat: bypass cropper for gifs
This commit is contained in:
		| @@ -228,6 +228,7 @@ define('forum/account/edit', ['forum/account/header', 'translator', 'components' | |||||||
|  |  | ||||||
| 			pictureCropper.show({ | 			pictureCropper.show({ | ||||||
| 				socketMethod: 'user.uploadCroppedPicture', | 				socketMethod: 'user.uploadCroppedPicture', | ||||||
|  | 				route: config.relative_path + '/api/user/' + ajaxify.data.userslug + '/uploadpicture', | ||||||
| 				aspectRatio: 1 / 1, | 				aspectRatio: 1 / 1, | ||||||
| 				paramName: 'uid', | 				paramName: 'uid', | ||||||
| 				paramValue: ajaxify.data.theirid, | 				paramValue: ajaxify.data.theirid, | ||||||
| @@ -235,7 +236,7 @@ define('forum/account/edit', ['forum/account/header', 'translator', 'components' | |||||||
| 				allowSkippingCrop: false, | 				allowSkippingCrop: false, | ||||||
| 				title: '[[user:upload_picture]]', | 				title: '[[user:upload_picture]]', | ||||||
| 				description: '[[user:upload_a_picture]]', | 				description: '[[user:upload_a_picture]]', | ||||||
| 				accept: '.png,.jpg,.bmp', | 				accept: ajaxify.data.allowedProfileImageExtensios, | ||||||
| 			}, function (url) { | 			}, function (url) { | ||||||
| 				onUploadComplete(url); | 				onUploadComplete(url); | ||||||
| 			}); | 			}); | ||||||
|   | |||||||
| @@ -18,6 +18,11 @@ define('pictureCropper', ['cropper'], function (Cropper) { | |||||||
| 				uploadModal.remove(); | 				uploadModal.remove(); | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
|  | 			var uploadForm = uploadModal.find('#uploadForm'); | ||||||
|  | 			if (data.route) { | ||||||
|  | 				uploadForm.attr('action', data.route); | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			uploadModal.find('#fileUploadSubmitBtn').on('click', function () { | 			uploadModal.find('#fileUploadSubmitBtn').on('click', function () { | ||||||
| 				$(this).addClass('disabled'); | 				$(this).addClass('disabled'); | ||||||
| 				data.uploadModal = uploadModal; | 				data.uploadModal = uploadModal; | ||||||
| @@ -170,21 +175,27 @@ define('pictureCropper', ['cropper'], function (Cropper) { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		var file = fileInput[0].files[0]; | 		var file = fileInput[0].files[0]; | ||||||
| 		var reader = new FileReader(); |  | ||||||
| 		var imageUrl; |  | ||||||
| 		var imageType = file.type; |  | ||||||
| 		var fileSize = data.hasOwnProperty('fileSize') && data.fileSize !== undefined ? parseInt(data.fileSize, 10) : false; | 		var fileSize = data.hasOwnProperty('fileSize') && data.fileSize !== undefined ? parseInt(data.fileSize, 10) : false; | ||||||
| 		if (fileSize && file.size > fileSize * 1024) { | 		if (fileSize && file.size > fileSize * 1024) { | ||||||
| 			return app.alertError('[[error:file-too-big, ' + fileSize + ']]'); | 			return app.alertError('[[error:file-too-big, ' + fileSize + ']]'); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if (file.name.endsWith('.gif')) { | ||||||
|  | 			require(['uploader'], function (uploader) { | ||||||
|  | 				uploader.ajaxSubmit(data.uploadModal, callback); | ||||||
|  | 			}); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var reader = new FileReader(); | ||||||
| 		reader.addEventListener('load', function () { | 		reader.addEventListener('load', function () { | ||||||
| 			imageUrl = reader.result; | 			var imageUrl = reader.result; | ||||||
|  |  | ||||||
| 			data.uploadModal.modal('hide'); | 			data.uploadModal.modal('hide'); | ||||||
|  |  | ||||||
| 			module.handleImageCrop({ | 			module.handleImageCrop({ | ||||||
| 				url: imageUrl, | 				url: imageUrl, | ||||||
| 				imageType: imageType, | 				imageType: file.type, | ||||||
| 				socketMethod: data.socketMethod, | 				socketMethod: data.socketMethod, | ||||||
| 				aspectRatio: data.aspectRatio, | 				aspectRatio: data.aspectRatio, | ||||||
| 				allowSkippingCrop: data.allowSkippingCrop, | 				allowSkippingCrop: data.allowSkippingCrop, | ||||||
|   | |||||||
| @@ -42,34 +42,38 @@ define('uploader', ['translator', 'benchpress'], function (translator, Benchpres | |||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	function onSubmit(uploadModal, fileSize, callback) { | 	function onSubmit(uploadModal, fileSize, callback) { | ||||||
| 		function showAlert(type, message) { | 		showAlert(uploadModal, 'status', '[[uploads:uploading-file]]'); | ||||||
| 			module.hideAlerts(uploadModal); |  | ||||||
| 			if (type === 'error') { |  | ||||||
| 				uploadModal.find('#fileUploadSubmitBtn').removeClass('disabled'); |  | ||||||
| 			} |  | ||||||
| 			uploadModal.find('#alert-' + type).translateText(message).removeClass('hide'); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		showAlert('status', '[[uploads:uploading-file]]'); |  | ||||||
|  |  | ||||||
| 		uploadModal.find('#upload-progress-bar').css('width', '0%'); | 		uploadModal.find('#upload-progress-bar').css('width', '0%'); | ||||||
| 		uploadModal.find('#upload-progress-box').show().removeClass('hide'); | 		uploadModal.find('#upload-progress-box').show().removeClass('hide'); | ||||||
|  |  | ||||||
| 		var fileInput = uploadModal.find('#fileInput'); | 		var fileInput = uploadModal.find('#fileInput'); | ||||||
| 		if (!fileInput.val()) { | 		if (!fileInput.val()) { | ||||||
| 			return showAlert('error', '[[uploads:select-file-to-upload]]'); | 			return showAlert(uploadModal, 'error', '[[uploads:select-file-to-upload]]'); | ||||||
| 		} | 		} | ||||||
| 		if (!hasValidFileSize(fileInput[0], fileSize)) { | 		if (!hasValidFileSize(fileInput[0], fileSize)) { | ||||||
| 			return showAlert('error', '[[error:file-too-big, ' + fileSize + ']]'); | 			return showAlert(uploadModal, 'error', '[[error:file-too-big, ' + fileSize + ']]'); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		module.ajaxSubmit(uploadModal, callback); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	function showAlert(uploadModal, type, message) { | ||||||
|  | 		module.hideAlerts(uploadModal); | ||||||
|  | 		if (type === 'error') { | ||||||
|  | 			uploadModal.find('#fileUploadSubmitBtn').removeClass('disabled'); | ||||||
|  | 		} | ||||||
|  | 		uploadModal.find('#alert-' + type).translateText(message).removeClass('hide'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	module.ajaxSubmit = function (uploadModal, callback) { | ||||||
| 		uploadModal.find('#uploadForm').ajaxSubmit({ | 		uploadModal.find('#uploadForm').ajaxSubmit({ | ||||||
| 			headers: { | 			headers: { | ||||||
| 				'x-csrf-token': config.csrf_token, | 				'x-csrf-token': config.csrf_token, | ||||||
| 			}, | 			}, | ||||||
| 			error: function (xhr) { | 			error: function (xhr) { | ||||||
| 				xhr = maybeParse(xhr); | 				xhr = maybeParse(xhr); | ||||||
| 				showAlert('error', xhr.responseJSON ? (xhr.responseJSON.error || xhr.statusText) : 'error uploading, code : ' + xhr.status); | 				showAlert(uploadModal, 'error', xhr.responseJSON ? (xhr.responseJSON.error || xhr.statusText) : 'error uploading, code : ' + xhr.status); | ||||||
| 			}, | 			}, | ||||||
| 			uploadProgress: function (event, position, total, percent) { | 			uploadProgress: function (event, position, total, percent) { | ||||||
| 				uploadModal.find('#upload-progress-bar').css('width', percent + '%'); | 				uploadModal.find('#upload-progress-bar').css('width', percent + '%'); | ||||||
| @@ -78,19 +82,19 @@ define('uploader', ['translator', 'benchpress'], function (translator, Benchpres | |||||||
| 				response = maybeParse(response); | 				response = maybeParse(response); | ||||||
|  |  | ||||||
| 				if (response.error) { | 				if (response.error) { | ||||||
| 					return showAlert('error', response.error); | 					return showAlert(uploadModal, 'error', response.error); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				callback(response[0].url); | 				callback(response[0].url); | ||||||
|  |  | ||||||
| 				showAlert('success', '[[uploads:upload-success]]'); | 				showAlert(uploadModal, 'success', '[[uploads:upload-success]]'); | ||||||
| 				setTimeout(function () { | 				setTimeout(function () { | ||||||
| 					module.hideAlerts(uploadModal); | 					module.hideAlerts(uploadModal); | ||||||
| 					uploadModal.modal('hide'); | 					uploadModal.modal('hide'); | ||||||
| 				}, 750); | 				}, 750); | ||||||
| 			}, | 			}, | ||||||
| 		}); | 		}); | ||||||
| 	} | 	}; | ||||||
|  |  | ||||||
| 	function parseModal(tplVals, callback) { | 	function parseModal(tplVals, callback) { | ||||||
| 		Benchpress.parse('partials/modals/upload_file_modal', tplVals, function (html) { | 		Benchpress.parse('partials/modals/upload_file_modal', tplVals, function (html) { | ||||||
|   | |||||||
| @@ -25,6 +25,7 @@ editController.get = async function (req, res, next) { | |||||||
| 	userData.allowProfilePicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:profile-picture']; | 	userData.allowProfilePicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:profile-picture']; | ||||||
| 	userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture']; | 	userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture']; | ||||||
| 	userData.allowProfileImageUploads = meta.config.allowProfileImageUploads; | 	userData.allowProfileImageUploads = meta.config.allowProfileImageUploads; | ||||||
|  | 	userData.allowedProfileImageExtensios = user.getAllowedProfileImageExtensions().map(ext => '.' + ext).join(', '); | ||||||
| 	userData.allowMultipleBadges = meta.config.allowMultipleBadges === 1; | 	userData.allowMultipleBadges = meta.config.allowMultipleBadges === 1; | ||||||
| 	userData.allowAccountDelete = meta.config.allowAccountDelete === 1; | 	userData.allowAccountDelete = meta.config.allowAccountDelete === 1; | ||||||
| 	userData.allowWebsite = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:website']; | 	userData.allowWebsite = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:website']; | ||||||
|   | |||||||
| @@ -1,14 +1,27 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| const winston = require('winston'); | const winston = require('winston'); | ||||||
|  | const mime = require('mime'); | ||||||
|  |  | ||||||
| const db = require('../database'); | const db = require('../database'); | ||||||
| const file = require('../file'); | const file = require('../file'); | ||||||
| const image = require('../image'); | const image = require('../image'); | ||||||
| const meta = require('../meta'); | const meta = require('../meta'); | ||||||
|  | const plugins = require('../plugins'); | ||||||
|  |  | ||||||
| module.exports = function (User) { | module.exports = function (User) { | ||||||
| 	const allowedTypes = ['image/png', 'image/jpeg', 'image/bmp']; | 	User.getAllowedProfileImageExtensions = function () { | ||||||
|  | 		return User.getAllowedImageTypes().map(type => mime.getExtension(type)); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	User.getAllowedImageTypes = function () { | ||||||
|  | 		const allowedTypes = ['image/png', 'image/jpeg', 'image/bmp']; | ||||||
|  | 		if (plugins.hasListeners('filter:image.isFileTypeAllowed')) { | ||||||
|  | 			allowedTypes.push('image/gif'); | ||||||
|  | 		} | ||||||
|  | 		return allowedTypes; | ||||||
|  | 	}; | ||||||
|  |  | ||||||
| 	User.updateCoverPosition = async function (uid, position) { | 	User.updateCoverPosition = async function (uid, position) { | ||||||
| 		// Reject anything that isn't two percentages | 		// Reject anything that isn't two percentages | ||||||
| 		if (!/^[\d.]+%\s[\d.]+%$/.test(position)) { | 		if (!/^[\d.]+%\s[\d.]+%$/.test(position)) { | ||||||
| @@ -30,7 +43,7 @@ module.exports = function (User) { | |||||||
| 				return await User.updateCoverPosition(data.uid, data.position); | 				return await User.updateCoverPosition(data.uid, data.position); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			validateUpload(data, meta.config.maximumCoverImageSize); | 			validateUpload(data, meta.config.maximumCoverImageSize, ['image/png', 'image/jpeg', 'image/bmp']); | ||||||
|  |  | ||||||
| 			picture.path = await getTempPath(data); | 			picture.path = await getTempPath(data); | ||||||
|  |  | ||||||
| @@ -63,7 +76,7 @@ module.exports = function (User) { | |||||||
| 				throw new Error('[[error:profile-image-uploads-disabled]]'); | 				throw new Error('[[error:profile-image-uploads-disabled]]'); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			validateUpload(data, meta.config.maximumProfileImageSize); | 			validateUpload(data, meta.config.maximumProfileImageSize, User.getAllowedImageTypes()); | ||||||
|  |  | ||||||
| 			const extension = file.typeToExtension(getMimeType(data)); | 			const extension = file.typeToExtension(getMimeType(data)); | ||||||
| 			if (!extension) { | 			if (!extension) { | ||||||
| @@ -92,7 +105,7 @@ module.exports = function (User) { | |||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	function validateUpload(data, maxSize) { | 	function validateUpload(data, maxSize, allowedTypes) { | ||||||
| 		if (!data.imageData && !data.file) { | 		if (!data.imageData && !data.file) { | ||||||
| 			throw new Error('[[error:invalid-data]]'); | 			throw new Error('[[error:invalid-data]]'); | ||||||
| 		} | 		} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user