mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
add server-side filesize check on uploads
This commit is contained in:
@@ -163,41 +163,55 @@ Discourse.Utilities = {
|
||||
/**
|
||||
Validate a list of files to be uploaded
|
||||
|
||||
@method validateFilesForUpload
|
||||
@method validateUploadedFiles
|
||||
@param {Array} files The list of files we want to upload
|
||||
**/
|
||||
validateFilesForUpload: function(files) {
|
||||
validateUploadedFiles: function(files) {
|
||||
if (!files || files.length === 0) { return false; }
|
||||
|
||||
// can only upload one file at a time
|
||||
if (files.length > 1) {
|
||||
bootbox.alert(I18n.t('post.errors.too_many_uploads'));
|
||||
return false;
|
||||
}
|
||||
|
||||
var upload = files[0];
|
||||
// ensures that new users can upload image/attachment
|
||||
if (Discourse.Utilities.isUploadForbidden(upload.name)) {
|
||||
if (Discourse.Utilities.isAnImage(upload.name)) {
|
||||
bootbox.alert(I18n.t('post.errors.image_upload_not_allowed_for_new_user'));
|
||||
} else {
|
||||
bootbox.alert(I18n.t('post.errors.attachment_upload_not_allowed_for_new_user'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// if the image was pasted, sets its name to a default one
|
||||
|
||||
// CHROME ONLY: if the image was pasted, sets its name to a default one
|
||||
if (upload instanceof Blob && !(upload instanceof File) && upload.type === "image/png") { upload.name = "blob.png"; }
|
||||
|
||||
return Discourse.Utilities.validateUploadedFile(upload, Discourse.Utilities.isAnImage(upload.name) ? 'image' : 'attachment');
|
||||
},
|
||||
|
||||
/**
|
||||
Validate a file to be uploaded
|
||||
|
||||
@method validateUploadedFile
|
||||
@param {File} file The file to be uploaded
|
||||
@param {string} type The type of the file
|
||||
**/
|
||||
validateUploadedFile: function(file, type) {
|
||||
// check that the uploaded file is authorized
|
||||
if (!Discourse.Utilities.isAuthorizedUpload(upload)) {
|
||||
if (!Discourse.Utilities.isAuthorizedUpload(file)) {
|
||||
var extensions = Discourse.SiteSettings.authorized_extensions.replace(/\|/g, ", ");
|
||||
bootbox.alert(I18n.t('post.errors.upload_not_authorized', { authorized_extensions: extensions }));
|
||||
return false;
|
||||
}
|
||||
// check file size
|
||||
var fileSizeKB = upload.size / 1024;
|
||||
var maxSizeKB = Discourse.Utilities.maxUploadSizeInKB(upload.name);
|
||||
if (fileSizeKB > maxSizeKB) {
|
||||
bootbox.alert(I18n.t('post.errors.upload_too_large', { max_size_kb: maxSizeKB }));
|
||||
|
||||
// ensures that new users can upload a file
|
||||
if (Discourse.User.current('trust_level') === 0 && Discourse.SiteSettings['newuser_max_' + type + 's'] === 0) {
|
||||
bootbox.alert(I18n.t('post.errors.' + type + '_upload_not_allowed_for_new_user'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// check file size
|
||||
var fileSizeKB = file.size / 1024;
|
||||
var maxSizeKB = Discourse.SiteSettings['max_' + type + '_size_kb'];
|
||||
if (fileSizeKB > maxSizeKB) {
|
||||
bootbox.alert(I18n.t('post.errors.' + type + '_too_large', { max_size_kb: maxSizeKB }));
|
||||
return false;
|
||||
}
|
||||
|
||||
// everything went fine
|
||||
return true;
|
||||
},
|
||||
@@ -238,27 +252,6 @@ Discourse.Utilities = {
|
||||
return path && path.match(/\.(png|jpg|jpeg|gif|bmp|tif|tiff)$/i);
|
||||
},
|
||||
|
||||
/**
|
||||
Retrieve max upload size in KB depending on the file is an image or not
|
||||
|
||||
@method maxUploadSizeInKB
|
||||
@param {String} path The path
|
||||
**/
|
||||
maxUploadSizeInKB: function(path) {
|
||||
return Discourse.Utilities.isAnImage(path) ? Discourse.SiteSettings.max_image_size_kb : Discourse.SiteSettings.max_attachment_size_kb;
|
||||
},
|
||||
|
||||
/**
|
||||
Test whether an upload is forbidden or not
|
||||
|
||||
@method isUploadForbidden
|
||||
@param {String} path The path
|
||||
**/
|
||||
isUploadForbidden: function(path) {
|
||||
if (Discourse.User.current('trust_level') > 0) { return false; }
|
||||
return Discourse.Utilities.isAnImage(path) ? Discourse.SiteSettings.newuser_max_images === 0 : Discourse.SiteSettings.newuser_max_attachments === 0;
|
||||
},
|
||||
|
||||
/**
|
||||
Determines whether we allow attachments or not
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ Discourse.ComposerView = Discourse.View.extend({
|
||||
|
||||
// submit - this event is triggered for each upload
|
||||
$uploadTarget.on('fileuploadsubmit', function (e, data) {
|
||||
var result = Discourse.Utilities.validateFilesForUpload(data.files);
|
||||
var result = Discourse.Utilities.validateUploadedFiles(data.files);
|
||||
// reset upload status when everything is ok
|
||||
if (result) composerView.setProperties({ uploadProgress: 0, isUploading: true });
|
||||
return result;
|
||||
@@ -300,10 +300,11 @@ Discourse.ComposerView = Discourse.View.extend({
|
||||
switch (data.jqXHR.status) {
|
||||
// 0 == cancel from the user
|
||||
case 0: return;
|
||||
// 413 == entity too large, returned usually from nginx
|
||||
// 413 == entity too large, usually returned from the web server
|
||||
case 413:
|
||||
var maxSizeKB = Discourse.Utilities.maxUploadSizeInKB(data.files[0].name);
|
||||
bootbox.alert(I18n.t('post.errors.upload_too_large', { max_size_kb: maxSizeKB }));
|
||||
var type = Discourse.Utilities.isAnImage(data.files[0].name) ? "image" : "attachment";
|
||||
var maxSizeKB = Discourse.SiteSettings['max_' + type + '_size_kb'];
|
||||
bootbox.alert(I18n.t('post.errors.' + type + '_too_large', { max_size_kb: maxSizeKB }));
|
||||
return;
|
||||
// 415 == media type not authorized
|
||||
case 415:
|
||||
|
||||
Reference in New Issue
Block a user